LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 3865|回复: 5

socket也可以使用mmap啦。

[复制链接]
发表于 2007-5-27 21:32:48 | 显示全部楼层 |阅读模式
如果你的内核提供了CONFIG_PACKET_MMAP选项,那么恭喜你,对网络包你可以采用mmap了,用了mmap,你就节省了内核从内核内存区拷贝到用户内存区的这一步,效率提高很多。
下面我们说说怎么用这么强的功能。

int fd;

fd= socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))
socket函数的protocal参数采用了ETH_P_ALL,表示抓取所有以太帧。SOCK_RAW表示抓取到的包的数据是IP包。
setsockopt(fd, SOL_PACKET, PACKET_RX_RING, (void *) &req, sizeof(req))
其中req参数是个结构,如下所示:
    struct tpacket_req
    {
        unsigned int    tp_block_size;  /* Minimal size of contiguous block */
        unsigned int    tp_block_nr;    /* Number of blocks */
        unsigned int    tp_frame_size;  /* Size of frame */
        unsigned int    tp_frame_nr;    /* Total number of frames */
    };
该结构是用来在内核中创建循环缓冲区,这个缓冲区随后会被映射到调用进程的用户空间。这块内存在内核中用block来组织,每个块是连续的物理内存区,每个块的大小是tp_block_size个字节,每个块最多可以装tp_block_size/tp_frame_size个帧。
这几个参数是由用户程序设置的,但有以下一些限制
tp_block_size 必须是 PAGE_SIZE 的倍数
tp_frame_size 必须大于 TPACKET_HDRLEN ,每个帧都有帧头结构用来描述meta信息,如时间戳
tp_frame_size 必须是 TPACKET_ALIGNMENT的倍数,TPACKET_ALIGNMENT的值是15。
tp_frame_nr   必须是frames_per_block*tp_block_nr
每个帧由以下的部件组成:
   - struct tpacket_hdr 帧头
   - pad  填充物,起对齐到16字节边界的作用
   - struct sockaddr_ll
   - Gap 填充物,起对齐到16字节边界的作用
   - Start+tp_mac: 可选mac地址
   - Start+tp_net: 包数据,16字节对齐
   - Pad to align to TPACKET_ALIGNMENT=16
如果用以下参数:

     tp_block_size= 4096
     tp_frame_size= 2048
     tp_block_nr  = 4
     tp_frame_nr  = 8
我们就得到了,如下的数据结构:
  1.         block #1                 block #2                   block #3                     block #4
  2. +---------+---------+       +---------+---------+      +---------+---------+      +---------+---------+
  3. | frame 1 | frame 2 |    | frame 3 | frame 4 |    | frame 5 | frame 6 |    | frame 7 | frame 8 |
  4. +---------+---------+       +---------+---------+      +---------+---------+       +---------+---------+
复制代码
接着用户程序使用
mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
映射后得到的是一个block数组,每个block中包含有若干帧。
程序直接就可以读这些内容了。
发表于 2007-5-29 11:57:07 | 显示全部楼层
补充:如果你的内核旧而不能使用MMAP的SOCKET,需要做高效率的SNIFFER工作,可以使用:http://public.lanl.gov/cpw/ 这个改良库,也使用了MMAP的方法来提高LIBPCAP的性能。

PS:我感觉版主的格式可以再调好看些:)
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-5-29 13:27:52 | 显示全部楼层
多谢kiron兄补充。
回复 支持 反对

使用道具 举报

发表于 2007-6-1 12:26:21 | 显示全部楼层
请教大侠一个问题:我们公司的系统是做高速包采集的,以前采用socket原始套接字收包,每秒只能处理100MB流量。后来采用了一个“零拷贝”网卡驱动,每秒可采集800MB流量。
零拷贝的很多资料说:“零拷贝”将来会成为网卡驱动的一个选项,不需要再编写了。

请问你的这种SOCKET的映射功能,在效率上和零拷贝比较起来怎么样呢?用PCAP采集包是否能在效率上与你提到的当时方式相当呢?请指教,谢谢!
回复 支持 反对

使用道具 举报

发表于 2008-7-1 16:22:11 | 显示全部楼层
好帖子,顶一个!!!!!!
回复 支持 反对

使用道具 举报

发表于 2011-2-26 17:17:31 | 显示全部楼层
时至今日,看到这个帖子的我激动不已。
对于4楼提到的问题,可以参考这里:
http://hi.baidu.com/ah__fu/blog/ ... 94ee35f9dc616c.html
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表