以DM9000网卡为例,剖析从网卡硬件中断开始,直到tcp、udp应用层读取到数据的过程
一 DM9000网卡驱动(这里我们仅仅分析最主要的流程,具体驱动程序可以自行阅读)
static struct platform_driver dm9000_driver = {
.driver = {
.name = "dm9000",
.pm = &dm9000_drv_pm_ops,
.of_match_table = of_match_ptr(dm9000_of_matches),
},
.probe = dm9000_probe,
.remove = dm9000_drv_remove,
};
网卡驱动标准
网卡驱动入口:dm9000_probe
网卡驱动出口:dm9000_drv_remove
(1) dm9000_probe
-->platform_get_irq() 注册一个中断,中断响应函数,dm9000_wol_interrupt()读取NSR,WCR寄存器
ndev->netdev_ops = &dm9000_netdev_ops;//设置网卡操作接口
-->register_netdev()
(2) 打开网卡dm9000_open()
注册收发数据中断
dm9000_interrupt()
{
dm9000_rx(dev);//收数据中断处理
dm9000_tx_done(dev, db);//数据发送完中断处理
}
dm9000_rx()
{
netdev_alloc_skb();//申请skb
netif_rx();//处理skb
}
netif_rx(skb)
{
netif_rx_internal(skb);//
}
//驱动的工作到此就结束了
二 linux内核网络模块处理skb
(1) 插入到事件通知队列
netif_rx_internal()
{
enqueue_to_backlog();//插入到cpu对应的__skb_queue_tail(&sd->input_pkt_queue, skb);队列
}
(2) 处理事件通知队列
net_dev_init()
{
open_softirq(NET_TX_SOFTIRQ, net_tx_action);//写数据软中断注册
open_softirq(NET_RX_SOFTIRQ, net_rx_action);//收数据软中断注册
hotcpu_notifier(dev_cpu_callback, 0);//热cpu通知回调
}
dev_cpu_callback()
{
netif_rx_ni(skb);//激活软中断
}
(3) 软中断处理过程
static void net_rx_action(struct softirq_action *h)
{
napi_poll();//
{//sd->backlog.poll = process_backlog;
n->poll(n, weight)
}
}
Poll 处理的是backlog队列
process_backlog()
{
__netif_receive_skb(skb);
{
__netif_receive_skb_core(skb, true);
{
deliver_skb();//发送到上层协议,比如ip协议,icmp协议
}
}
}
四 下一节分析上层协议处理过程,敬请关注