关于收包流程的研究
【提出问题】
1、网卡收包流程是怎么样的?
网卡收包流程是怎么样的?
网络驱动收包大致存在3中情况:
1、no NAPI: mac每收到一个以太网包,都会产生一个接收中断给cpu,即完全靠中断方式来收包。缺点就是当网络流量很大时,cpu大部分时间都耗在了处理mac中断上。
2、netpoll:在网络和I/O子系统尚不能完整可用时,模拟了来自指定设备的中断,即轮询收包。(依次发出询问是否要收包)缺点是实时性差。
3、NAPI:就是上面两种情况的折中。数据量少时采用中断,数据量多时采用轮询。mac收到一个包来后会产生接收中断,但是马上关闭。直到收够了netdev_max_backlog个包(默认300),或者收完mac上所有包后,才再打开接收中断。
通过sysctl来修改 net.core.netdev_max_backlog
或者通过proc修改 /proc/sys/net/core/netdev_max_backlog
介绍三种关键数据结构:
sk_buff
功能:一种缓存,适配不同的协议,在不同的数据结构中传递。
softnet_data
功能:NIC和网络层之间的处理队列,从NIC和POLL之间传递信息。
net_device
功能:这个dev指针会指向收到数据包的网络设备。
大致的流程如下图:
网卡多队列的情况
http://note.youdao.com/noteshare?id=e08e41f79ffacedc792ef4444ab7ff1d&sub=A783644358AC4CA4B2912D2DBEEBB7E9
【提出疑问】
1、收包过程中深层次原理是怎样的?
2、软中断中是如何使用NAPI的?
收包过程中深层次原理是怎样的?
softirq(软中断)
此为中断处理“下半部”机制。中断服务程序一般都是在中断请求关闭的条件下执行的,以避免嵌套而使中断控制复杂化。但是,中断是一个随机事件,它随时会到来,如果关中断的时间太长,CPU就不能及时响应其他的中断请求,从而造成中断的丢失。因此,Linux内核的目标就是尽可能快的处理完中断请求,尽其所能把更多的处理向后推迟。这也就是内核的上半部和下半部。
top中si就是软中断,在ps -elf中ksoftirqd就是软中断的一个守护进程,且每个cpu一个守护进程。
上半部处理硬中断
1、接收到数据包后关闭硬中断
2、标记NAPI_STATE_SCHED 状态
3、将网络设备挂到轮询列表中
4、触发网络接收软中断,开始下半部处理
下半部处理软中断
1、遍历轮询列表
2、从轮询列表中取出napi_struct结构,执行钩子函数napi_struct.poll()
3、若poll钩子函数处理完所有包,打开收包活动掩码,再来数据包的话会产生rx中断
4、调用函数,结束napi
5、将网络设备从轮询列表中移走,同时去掉NAPI_STATE_SCHED 状态的标记
软中断中是如何使用NAPI的?
在进入网卡中断时会初始化一个budget(系统预算),即最多处理的网络包个数,如果有多个网卡(放在poll_list里),是共享该budget,同时每个网卡也一个权重weight或者说是配额quota。若quota用完,则放到轮询队列尾部,重新设置一下quota的值以等待while轮询。若quota没有用完且收到的包不多,这时网卡比较空闲,那该设备就会从轮询列表中摘除。
【提出疑问】
1、什么是钩子函数?
什么是钩子函数?
钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。