我的程序无法从以太网映射 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 run
命令中:--ulimit memlock=150994944
来自
mmap
的错误意味着您要求的 MAP_LOCKED
内存超出了允许的范围。问题是 Docker 默认提供的 ulimit 非常低。您可以通过在容器内部和外部运行 ulimit -Sl
和 ulimit -Hl
并比较它们来看到这一点(但要注意 bash 使用 KB,而 Docker 需要字节)。上述参数将为您提供 144MB 的 ulimit。