目前在网络世界TCP/IP占统治地位。linux由于其开源特性发展很快。现在在做研究的时候需要用到这方面的知识,于是边学习边总结,由于研究的内容主要集中在TCP/IP的底层,所以在这里主要分析底层的实现。
我在这里研究的代码主要是如下图所示(图片来源于网络)
这里用的图片是一个路由器的图片。
我们在后面的介绍中将分接收数据包和发送数据包来进行分析。
一:接收数据包。
在最开始的linux内核里面接收网络数据都是只有触发硬中断这种方式。后来引入了软中断,这个与信号比较相似。"硬中断是外部设备对CPU的中断","软中断通常是硬中断服务程序对内核的中断","信号则是由内核(或其他进程)对某个进程的中断"(《Linux内核源代码情景分析》第三章)。
目前的主流内核2.6X以后(前面的没了解)接收数据包的流程:数据包到达网络设备后,会触发硬中断,系统将设备加入轮询队列,然后关闭硬中断打开软中断。在软中断中,读取轮询队列中网络设备的数据包。这个在后面详细介绍。
系统中与此相关的全局参数主要有五个:
dev_weight软中断中单个网络设备的缓存配额,达到后就换下一个设备继续读。
netdev_budget 所有网络设备的缓存配额之和,达到后结束读取,开始下一轮软中断。
netdev_max_backlog 非NAPI链路层的缓存队列配额上限。
message_burst /message_cost这个是两个安全相关的参数,主要是防止DDOS攻击。
目前网卡处理数据包的接受主要分 NAPI和非NAPI两种方式。当第一个数据包到达的时候,网卡会以硬中断的方式告诉系统,这个硬中断的处理例程如下:将该设备加入到cpu的设备轮询(轮询在大流量数据处理的时候就不那么低效了)队列中,并关闭硬中断,同时打开数据包输入软中断,由软终端遍历轮询队列中的网络设备,并从中读取数据包。这样,在内核接收网络设备的数据包的此次过程中不再需要中断,NAPI只需要维护网络设备轮询队列就可以了。当全部设备完成读取后或者其他特殊条件的时候,这个过程终止,软中断结束,硬中断重新开始,新一个过程开始。
NAPI:这种方式的特点是每一次数据包到来的时候都会产生硬中断,这样的话好处是处理的比较及时,坏处是如果网络设备流量特别大的话将会非常厉害的消耗系统资源,造成系统性能下降。