docker mmap 资源暂时不可用

问题描述 投票:0回答:1

我的程序无法从以太网映射 docker 中的内存。

docker run --rm -it -e "PYTHONUNBUFFERED=1" --network=host snf
    int packet_socket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_IP));
    if (packet_socket == -1) {
        printf("Can't create AF_PACKET socket: %s\n", strerror(errno));
        return -1;
    }

    int version = TPACKET_V3;
    int setsockopt_packet_version = setsockopt(packet_socket, SOL_PACKET, PACKET_VERSION, &version, sizeof(version));

    if (setsockopt_packet_version < 0) {
        printf("Can't set packet v3 version\n");
        return -1;
    }

    int interface_number = get_interface_number_by_device_name(packet_socket, interface_name);
    if (interface_number == -1) {
        printf("Can't get interface number by interface name\n");
        return -1;
    }

    struct packet_mreq sock_params;
    memset(&sock_params, 0, sizeof(sock_params));
    sock_params.mr_type = PACKET_MR_ALLMULTI;
    sock_params.mr_ifindex = interface_number;

    int set_promisc = setsockopt(packet_socket, SOL_PACKET, PACKET_ADD_MEMBERSHIP, (void *) &sock_params, sizeof(sock_params));
    if (set_promisc == -1) {
        printf("Can't enable promisc mode: %s\n", strerror(errno));
        return -1;
    }

    struct sockaddr_ll bind_address;
    memset(&bind_address, 0, sizeof(bind_address));

    bind_address.sll_family = AF_PACKET;
    bind_address.sll_protocol = htons(ETH_P_ALL);
    bind_address.sll_ifindex = interface_number;

    struct tpacket_req3 req;
    memset(&req, 0, sizeof(req));

    req.tp_block_size = blocksiz;
    req.tp_frame_size = framesiz;
    req.tp_block_nr = blocknum;
    req.tp_frame_nr = (blocksiz * blocknum) / framesiz;

    req.tp_retire_blk_tov = 60; // Timeout in msec
    req.tp_feature_req_word = TP_FT_REQ_FILL_RXHASH;

    int setsockopt_rx_ring = setsockopt(packet_socket, SOL_PACKET , PACKET_RX_RING , (void *) &req , sizeof(req));
    if (setsockopt_rx_ring == -1) {
        printf("Can't enable RX_RING for AF_PACKET socket: %s\n", strerror(errno));
        return -1;
    }

    uint8_t* mapped_buffer = NULL;
    struct iovec *rd = NULL;
    mapped_buffer = (uint8_t *) mmap(NULL, req.tp_block_size * req.tp_block_nr, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, packet_socket, 0);
    if (mapped_buffer == MAP_FAILED) {
        printf("mmap failed: %d %s\n", errno, strerror(errno));
        return -1;
    }

我尝试从 docker 中的套接字映射(~128 MB)数据。我有两个线程,每个线程尝试映射 64 MB,但我得到:

mem: 64 mb per iface; cores: 2 per iface 
mmap failed: 11 Resource temporarily unavailable 
mmap failed: 11 Resource temporarily unavailable

我尝试从 sudo 运行 docker,从 root 启动 docker 中的应用程序。同样的错误。 当我在没有 Docker 的情况下启动它时,一切正常。

docker mmap ethernet
1个回答
0
投票

将此添加到您的

docker run
命令中:
--ulimit memlock=150994944

来自

mmap
的错误意味着您要求的
MAP_LOCKED
内存超出了允许的范围。问题是 Docker 默认提供的 ulimit 非常低。您可以通过在容器内部和外部运行
ulimit -Sl
ulimit -Hl
并比较它们来看到这一点(但要注意 bash 使用 KB,而 Docker 需要字节)。上述参数将为您提供 144MB 的 ulimit。

© www.soinside.com 2019 - 2024. All rights reserved.