网络协议栈16:connect函数分解之链路层接收数据

Connect函数在发送了数据之后,就进入了休眠等待的状态,等待远方发过来的数据来确认链接是否成功。那么数据是如何从网卡那里传递到链路层?

 

数据在网卡的内存中,形成了以256字节为1页的环形缓冲链,每当有数据到达,网卡就会发生一个中断信号,告诉CPU已经有数据到达,此时,CPU通过DMA的方式,去读取网卡内存中的数据,并把数据存放在一个专门开辟来接收这个数据包的skb_buff中,之后,就把接收数据的skb_buff进行排列,并且累加所有skb_buff的个数,如果超过一定的数量在排队等待被取走,则后面不能再继续从网卡中读取数据包,以防止系统内存被过度的消耗掉。因此,在数据链路层,skb_buff是被排成一个队列,达到FIFO的目的。

一般接收数据都是在中断中完成,而中断时需要快速的进行处理,以免消耗系统过多的资源,因此,把数据进行队列排队后,就要离开中断处理函数了,此时,需要启动中断程序的后半部来进行剩余的数据的处理。

net_bh()函数是接收中断处理函数的后半部处理函数,其主要的工作是

1.  把还在链路层中排队,还没有发送出去的数据包发送送出去(可见发送数据包是很重要的)。

2.  把在接收队列中排队的数据包的上层协议类型都找出来,准备把数据发送往对应的协议层(遍历协议类型链表,即struct packet_type所组成的链表,来找到需要发送的数据包所对应的上层协议)。

3.  调用相应的上层协议的接收函数来接收数据包。

 

上层协议的接收函数,是在操作系统初始化的时候,就已经初始化好了,其实就是注册

struct packet_type {

  unsigned short    type;       /* This is really htons(ether_type). */

  struct device *    dev;

  int                     (*func) (struct sk_buff *, struct device *,

                             struct packet_type *);

  void                  *data;

  struct packet_type      *next;

};

 

这样的结构体(比如static struct packet_type ip_packet_type,static struct packet_type arp_packet_type),其中的func指针所指向的,就是type所确定的协议类型的接收函数,type可取类型如下

#define ETH_P_LOOP  0x0060           /* Ethernet Loopback packet  */

#define ETH_P_ECHO  0x0200           /* Ethernet Echo packet        */

#define ETH_P_PUP     0x0400           /* Xerox PUP packet            */

#define ETH_P_IP        0x0800           /* Internet Protocol packet    */

#define ETH_P_ARP     0x0806           /* Address Resolution packet */

#define ETH_P_RARP 0x8035           /* Reverse Addr Res packet   */

#define ETH_P_X25     0x0805           /* CCITT X.25                     */

#define ETH_P_ATALK 0x809B          /* Appletalk DDP          */

#define ETH_P_IPX      0x8137           /* IPX over DIX                  */

#define ETH_P_802_3   0x0001           /* Dummy type for 802.3 frames  */

#define ETH_P_AX25   0x0002           /* Dummy protocol id for AX.25  */

#define ETH_P_ALL     0x0003           /* Every packet (be careful!!!) */

#define ETH_P_802_2   0x0004           /* 802.2 frames            */

#define ETH_P_SNAP  0x0005           /* Internal only             */

 

 

posted on 2012-01-18 12:16  image eye  阅读(874)  评论(0编辑  收藏  举报