Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1366339
  • 博文数量: 118
  • 博客积分: 3888
  • 博客等级: 中校
  • 技术积分: 2940
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-10 18:15
个人简介

一看二做三总结

文章分类

全部博文(118)

分类: LINUX

2010-09-05 18:51:55

本文乃fireaxe原创,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,并注明原作者及原链接,严禁用于任何商业用途。
作者:fireaxe_hq@hotmail.com
博客:fireaxe.blog.chinaunix.net 

    协议栈是用来处理网口数据的,数据当然是来自于网口。网口驱动程序是与硬件相关的,它会把数据从网口取出来后放在一个队列中。协议栈就通过不断的读取这个队列来获得待处理数据。通过这种方式,可以保证协议栈的硬件无关性,它不用管数据时怎么来的,甚至不用管是不是硬件来的(可以通过程序直接把数据放到队列中去),只要去读队列就行了。

    以CS8900a为例。CS8900a为CIRRUS LOGIC公司生产的低功耗、性能优越的16位以太网控制器,应用非常广泛。它的驱动在文件driver/net/cs8900/cs8900.c中。

    cs8900_interrupt是中断处理函数,当有数据收发或者其他信号被触发时,会调用该函数。首先从PP_ISQ中读出中断状态,如果是网口设备接到了数据,则中断状态为RxEvent,调用函数cs8900_receive处理数据。cs8900_receive读出数据放到skb中,并送给函数netif_rx处理。netif_rx中调用__skb_queue_tail把接收到的数据放到接收队列input_pkt_queue中。到此网口驱动就完成了数据处理的工作。其实netif_rx就已经是标准函数了,任何一款网口的驱动都会调用这个函数把数据送入协议栈。由于其标准性,它的实现是在文件net/core/dev.c中。

    接下来的操作用到了一个叫软中断的机制。下面的代码会绑定一个软中断处理函数:

    open_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL);

    当中断NET_RX_SOFTIRQ被触发时,处理函数net_rx_action会被调用。那么怎么触发软中断呢,它又没有硬件触发? 既然是软中断,当然是软件触发,通过函数__raise_softirq_irqoff触发,调用下面的代码后,会触发一个软中断:

    __raise_softirq_irqoff(NET_RX_SOFTIRQ);

    net_rx_action中通过下面这句进行数据的处理:

    work = n->poll(n, weight);

    poll是一个回调函数,它根据挂的回调的不同而进行不同的处理。系统默认的处理函数是process_backlog,该函数中调用__skb_dequeue获得之前放到队列input_pkt_queue中的数据取出来,传入函数netif_receive_skb处理。netif_receive_skb中会根据收到数据的格式调用相应的处理函数:

    ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);

    如果是以太网报文,则会调用结构体ip_packet_type中定义的处理函数ip_rcv。

    从ip_rcv开始,就正式进入协议栈处理流程。

    总结:

    网口驱动数据---->放入队列---->触发软中断---->从队列中取数据---->传给协议栈处理

    关于软中断机制可参考

本文乃fireaxe原创,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,并注明原作者及原链接,严禁用于任何商业用途。
作者:fireaxe_hq@hotmail.com
博客:fireaxe.blog.chinaunix.net 
阅读(3546) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~