Pf_ring (翻译)
一,研究开源的
Mmp_libpcap 没有解决数据到网卡的效率问题,
1. 网卡收到的数据被拷贝到环形缓冲区中,PF_RING套接字依赖于环形缓冲区
1. 套接字被创建时,创建环形缓冲区, 不同的套接字创建不同的环形缓冲区.
2. 当套接字绑定网卡时,这个网卡一直在可读模式,一直到该套接字被释放
3. 当从网卡接受数据时(当然一般是通过DMA ,直接内存访问),驱动向协议栈提交数据(linux 通过netif_receive_skb 和 netif_rx 函数,依赖于轮询是否启用),而 pf_ring 套接字时,每一个包会被拷贝一份到环形队列中, 或者丢弃,如果buffer 为满的时候,也被丢弃
4. 用PF_RING套接字接受数据,默认不直接传输到上层,而是被拷贝到环形队列后,丢弃掉,这样会增加性能,因为没有必要被上层处理,只是被环形队列处理
5. ring 缓冲区映射到用户空间通过mmap
6. 用户应用程序向访问ring buffer , 需要打开文件,调用mmap() ,获得指向环形buffer 句柄
7. 内核拷贝数据到环形队列,并且移动写指针,用户空间操作方法相同
8. 新到的数据包把以前的数据包覆盖,如果用户空间已经读结束,内存不在分配,只是简单覆盖
9. 缓存的长度,是完全由用户配置的,对所有的sockets 都一样。
位于缓冲区的socket 多用途的,包括
1. 包不排队到内核的数据结构上去
2. mmap 允许用户应用程序访问ring buffer ,用系统调用直接用sockets
3. 即使内核不支持设备轮询,使用该系统还是有用的,这是因为处理中断的时间是非常有限的,与正常的数据包处理相比
4. 对数据包的过滤是非常简单有效的,因为数据包没有必要传递给协议层,被丢弃掉了,因为它是以libpcap为基础的应用程序
5. 多个应用程序可以同时打开多个pf_ring socket而没有交叉,(比如运行慢的应用对运行快的应用没有干扰)
正常的抓包和现在不同是,现在需要重新编译库文件,现在的包存放在ring buffer 中,不在内核的数据结构中,由于这些原因,作者扩展了pf_ring
三.
Pf_ring 已经明显改进抓包性能,但是它有两个缺陷
1, 它需要一个实时的补丁去改进系统调用的性能,特别是轮询
2, 另外受限于网络驱动的编写,和NAPI 从网卡中获取包
在最后几个月,那个实时补丁采用一个适应性的轮询算法,当没有包处理时,库休息
一定的时间.
一,中断
1. 网卡产生中断(通知内核有包到来),如果包流量很大的情况,操作系统花费大部分时间处理中断,只剩余很少时间去处理其它事物,解决这个问题就是用轮询技术,轮询是处理设备的方法:特点如下
1. 当一个网络设备接受到数据包,产生一个中断
系统接受到数据包进行如下操作
1. 屏蔽网卡中断(也就是说网卡不能对内核中断)
2. 开始分配一个任务去周期性的轮询设备来满足需要
3. 一旦内核轮询到该设备的时候,网卡才产生中断
这样可以提高系统性能