文档详情

Linux内核网络协议栈笔记4 接收网络数据包详细过.doc

发布:2018-10-22约4.23千字共6页下载文档
文本预览下载声明
Linux内核网络协议栈笔记4 接收网络数据包详细过 Linux内核网络协议栈笔记4:接收网络数据包详细过程2010-08-10 15:41网络数据接收过程,从数据包到达网卡的物理接口开始,然后由网卡的驱动程序交给网络协议栈,最后经过协议栈的一层层处理之后交给应用程序。大致上是这样的过程,但实际上有更多的细节。本文中主要介绍第一个和第二个步骤。 我们本文中依然以一个Realtek 8139网卡为例(驱动程序为/drivers/net/8139too.c)。请注意在内核代码中receive都是用rx简写的。 (1)注册与激活软中断 在生成net_device对象及初始化的函数rtl8139_init_one中已经初始化dev-open方法为rtl8139_open函数(在本系列文章2:初始化中的net_device对象中已经介绍,点这里查看)。在rtl8139_open函数(这个函数在网卡启动时被调用)中注册了一个中断函数rtl8139_interrupt: retval=request_irq(devirq,rtl8139_interrupt,SA_SHIRQ,devname,dev);所以只要当网卡开启后(状态为up),当网络数据包到达时,都会产生一个硬件中断(这不同于后面的软中断)。这个硬件中断由内核调用中断处理程序rtl8139_interrupt函数处理。这个函数比较重要,网卡发送或者接收数据时内核都会调用这个函数处理中断,而中断的类型是根据网卡状态寄存器的不同而确定的。本文中仅涉及接收数据的中断,因此只给出了接收的代码: staticirqreturn_t rtl8139_interrupt(intirq,void*dev_instance,structpt_regs*regs) { if(statusRxAckBits){ if(netif_rx_schedule_prep(dev)) __netif_rx_schedule(dev); } }主要函数为__netif_rx_schedule(函数名意为:network interface receive schedule,即网络接口接收调度),因为当网卡接收到数据包之后,马上告知CPU在合适的时间去启动调度程序,轮询(poll)网卡。 请注意:Linux接收网络数据实际上有两种方式。 (a)中断。每个数据包到达都会产生一个中断,然后由内核调用中断处理程序处理。 (b)NAPI(New API)。Linux内核2.6版本之后加入的新机制,核心方法是:不采用中断的方式读取数据,而代之以首先采用中断唤醒数据接收的服务程序,然后以POLL的方法来轮询数据。 因此本文中只介绍NAPI的接收方式。我们不再详细介绍这种机制,网上可找到比较多的资料,可以参考IBM的技术文章:NAPI技术在Linux网络驱动上的应用和完善。__netif_rx_schedule函数的定义如下: staticinlinevoid__netif_rx_schedule(structnet_device*dev) { local_irq_save(flags);//disable interrupt //Add interface to tail of rx poll list list_add_tail(devpoll_list,__get_cpu_var(softnet_data).poll_list); //activate network rx softirq __raise_softirq_irqoff(NET_RX_SOFTIRQ); local_irq_restore(flags); }这个函数最核心的就是三步: (a)local_irq_save:禁用中断 (b)list_add_tail:将设备添加到softnet_data的poll_list中。 (c)激活一个软中断NET_RX_SOFTIRQ。 == 说到这里我们必须介绍一个关键数据结构softnet_data,每个CPU都拥有一个这样的网络数据队列(所以函数中使用了__get_cpu_var函数取得),定义如下: structsoftnet_data { int throttle;/*为1表示当前队列的数据包被禁止*/ int cng_level;/*表示当前处理器的数据包处理拥塞程度*/ int avg_blog;/*某个处理器的平均拥塞度*/ structsk_buff_head input_pkt_queue;/*接收缓冲区的sk_buff队列*/ structlist_head poll_list;/*POLL设备队列头*/ structnet_device output_queue;/*网络设备发送队列的队列头*/
显示全部
相似文档