数据包接收处理流程
- 系统启动时,在kernel/softirq.c文件中函数spawn_ksoftirq会调用smpboot_register_percpu_thread,这个函数位于kernel/smpboot.c文件中,他的作用就是为每一个cpu注册一个软中断的线程处理函数,而这个软中断处理线程函数名称为run_ksoftirqd
- 软中断线程入口函数run_ksoftirqd会检测softirq的pengding位是否置位,如果置位则调用__do_softirq();
- 位于文件kernel/softirq.c中的函数__do_softirq会根据pending位去找到注册软中断softirq的action函数,然后执行注册函数。
- 系统启动时,位于/net/core/dev.c文件中的net_dev_init函数将注册softirq,NET_RX_SOFTIRQ对应的软中断入口函数为net_rx_action
- 位于/net/core/dev.c文件中的net_rx_action函数会调用napi_poll函数,最终对调用到驱动的poll函数,这就是驱动接收数据包的入口函数。比如nxp的以太网驱动里边的lpc_eth_poll就是poll的入口
有了上面的描述,我们知道的软中断的入口,但是从数据包到达网卡之后怎么触发中断的呢?
- 网卡接收到数据包,网卡将DMA的数据写入RAM中
- 网卡向CPU触发硬中断
- CPU调用硬中断处理函数,这里我们以nxp的以太网卡驱动进行说明,内核版本4.1.35,文件名称:/driver/net/ethernet/nxp/lpc_eth.c,驱动程序入口函数lpc_eth_drv_probe会注册硬中断处理函数,注册代码如下:
这说明nxp以太网卡驱动的硬中断入口函数为__lpc_eth_interrupt.ret = request_irq(ndev->irq, __lpc_eth_interrupt, 0, ndev->name, ndev);
- 硬中断处理函数清除硬中断的IRQ标志位,调用__net_schedule。实际的代码如下
tmp = readl