linux网络设备驱动

  网络设备是完成用户数据包在网络媒介上发送和接受的设备,它将上层协议传下来的数据包以特定的媒介访问控制方式进行发送。并将接收到的数据包传送给上层协议。网络设备并不对应于/dev目录下的文件,应用程序使用套接字完成与网络设备的接口。

第一部分  Linux网络设备驱动的结构

  Linux网络设备程序的体系结构如下图所示,由上到下依次分为4层,依次为网络协议接口层、网络设备接口层、设备驱动功能层和网络设备与媒介层。

  

  (1)网络协议接口层

    网络协议接口层主要的功能是给上层协议提供透明的数据包发送和接收接口,当上层ARP或者IP需要发送数据包时,它会调用网络协议接口层的dev_queue_xmit()函数发送数据包,并通过netif_rx()函数接收数据包,这一层的存在使得上层协议独立于具体的设备。

  常用数据结构及函数分析:

  sk_buff 用于在Linux网络子系统的各层之间传递数据,是Linux网络子系统数据传输的“中枢神经”,位于include/linux/skbuff.h文件中。  

  int dev_queue_xmit(struct sk_buff *skb)    是网络协议接口层向下发送数据的接口, 内核已经实现, 不需要网络设备驱动实现

  int netif_rx(struct sk_buff *skb)  是网络设备接口层向上发送数据的接口, 不需要网络驱动实现

  a、分配套接字缓冲区的函数

  struct sk_buff  *alloc_skb(unsigned int len, gfp_t priority);    //分配一个长度为len的套接字缓冲区

  struct sk_buff *dev_alloc_skb(unsigned int len);   //以GFP_ATOMIC优先级进行skb的分配,该函数经常在设备驱动的接收中断里面调用。

  b、释放套接字缓冲区

  void  kfree_skb(struct sk_buff *skb);    //用于内核内部

  void dev_ kfree_skb(struct sk_buff *skb);   //用于非中断上下文

  void  dev_kfree_skb_irq(struct sk_buff *skb);   //用于中断上下文

  void  dev_kfree_skb_any(struct sk_buff *skb);   //中断和非终端皆可

  c、变更

  unsigned char *skb_put(struct sk_buff *skb, unsigned int len);  //在缓冲区尾部增加长度为len的数据

  unsigned char *skb_push(struct sk_buff *skb, unsigned int len);  //在缓冲区开头增加长度为len的数据 void d

  static inline void skb_reserve(struct sk_buff *skb, int len);  //skb->data和skb->tail同时后移len

 (2)网络设备接口层

   网络设备接口层的主要功能是为千变万化的网络设备定义统一、抽象的数据结构net_device结构体,以不变应万变,实现多种硬件在软件层面上的统一。net_device结构体在内核中指代一个网络设备,它定义于include/linux/netdevice.h文件,包含网络设备的属性描述和操作接口。网络设备驱动程序只需要通过填充net_device的具体成员并注册net_device即可实现硬件操作函数与内核的挂接,该结构体需要驱动工程师自己实现。 

  net_device->net_device_ops是网络设备的一系列硬件操作函数的集合,该函数需要在设备驱动功能层(dm9000.c)实现。

   (3)设备驱动功能层(具体的硬件驱动)

  a、实现net_device结构体的成员(属性和net_device_ops结构体中的函数指针);

  b、实现接收中断处理函数,将硬件接收到的数据包传送给上层协议。

 

第二部分  网络设备的收发流程

  Linux网络子系统在发送数据包时,会调用驱动程序提供的hand_start_transmit()函数,该函数用于启动数据包的发送,在设备初始化的时候,这个函数指针须被初始化以指向设备的xxx_tx函数,数据发送流程如下:

  a、网络设备驱动程序从上层协议传递过来的sk_buf参数获得数据包的有效数据和长度,将有效数据放入临时缓冲区。

  b、对于以太网,如果有效数据的长度小于以太网冲突检测所要求数据帧的最小长度ETH_ZLEN,则给临时缓冲区的末尾填充0。

  c、设置硬件寄存器,驱使网络设备进行数据发送操作。

 

  Linux网络设备接收数据的主要方法是由中断引发设备的中断处理函数,中断处理函数判断中断类型,如果为接收中断,则读取接收到的数据,分配sk_buff数据结构和数据缓冲区,将接收到的数据填充的数据缓冲区,并调用netif_rx函数将sk_buff传递给上层协议。

 

posted @ 2018-12-21 22:26  ZQ_One  阅读(739)  评论(0)    收藏  举报