Linux网络设备驱动程序

Linux网络设备驱动程序体系结构

--------------------------------------
    |        数据包发送    |    数据包接收      |    ----->网络协议接口层
    |  dev_queue_xmit() |    netif_rx()      |
    |--------------------------------------
    |            结构体 net_device          |    ----->网络设备接 口层
    --------------------------------------
    |        数据包发送      |      中断处理      |    ----->网络驱动功能层
    |  hard_start_xmit() |    数据包接收      |
    |--------------------------------------
    |        网络设备媒介(物理层)          |    ----->网络设备与媒介层
    --------------------------------------

硬件相关的驱动程序(要提供hard_start_xmit, 有数据时要用netif_rx上报)

5.sk_buff套接字缓冲区,用于linux中各层之间传输数据。当要发送数据包的时候,内核必须建立一个包含传输数据的sk_buff
然后将sk_buff交给下层,各层在sk_buff递交给下一层,各层在sk_buff中添加不同的协议贞头,直到交给网络设备发送。接收原理相同。
struct sk_buff {
 /* These two members must be first. */
 struct sk_buff *next;
 struct sk_buff *prev;
 /*网络设备接口层中的net_devive结构体*/
struct net_device *dev;
 ....

/*控制缓冲区 ,每个层都可以使用它,用于存放私有数据*/
char cb[48];

unsigned int len, //数据真实长度
data_len,//数据长度
mac_len; //链接层帧头的长度
/*钩子函数 垃圾回收*/
void (*destructor)(struct sk_buff *skb);

sk_buff_data_t transport_header;
 sk_buff_data_t network_header;
 sk_buff_data_t mac_header;
 /* These elements must be at the end, see alloc_skb() for details. */
 sk_buff_data_t tail;
 sk_buff_data_t end;
 unsigned char *head,
 *data;
 unsigned int truesize;
 atomic_t users;
 };
5.1、sk_buff结构:
----------- ---->*head
 | 头部 |
 |------------ ---->*data
 | 数据 |
 | 缓存 |
 |----------- ---->*tail
 | 尾部 |
----------- ---->*end

5.2、分配:
 分配套接字缓冲区:以GFP_ATOMIC优先级进行skb的分配,因为该函数经常在设备驱动中被调用
static inline struct sk_buff *dev_alloc_skb(unsigned int length)

分配一个套接字缓冲区和一个数据缓冲区,参数len为数据缓冲区的大小,ARM通常32位对齐,参数priority为内存分配的优先级。
static inline struct sk_buff *alloc_skb(unsigned int size,gfp_t priority)

5.3、释放:
//用于释放dev_alloc_skb的内存,用于非中断上下文中
void dev_kfree_skb(struct sk_buff *skb)
 //用于中断上下文中
static inline void dev_kfree_skb_irq(struct sk_buff *skb)
 //中断和非中断都可以用 any,其实就是做了一个判断
void dev_kfree_skb_any(struct sk_buff *skb)
 {
 if (in_irq() || irqs_disabled())
 dev_kfree_skb_irq(skb);
 else
 dev_kfree_skb(skb);
 }
5.4、变更:
 缓冲区尾部增加数据 skb
 static inline unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
 skb->tail += len;
 skb->len += len;

缓冲区开头增加数据
static inline unsigned char *skb_push(struct sk_buff *skb, unsigned int len)
 skb->data -= len;
 skb->len += len;

缓冲区开头移除数据
static inline unsigned char *skb_pull(struct sk_buff *skb, unsigned int len)
 skb->len -= len;
 return skb->data += len;

调节缓冲区头部
static inline void skb_reserve(struct sk_buff *skb, int len)
 skb->data += len;
 skb->tail += len;

6.net_device结构体
struct net_device
 {
 /*网络设备名称*/
char name[IFNAMSIZ];

unsigned long mem_end; /* 共享内存结束地址 */
unsigned long mem_start; /* 共享内存开始地址 */
unsigned long base_addr; /* I/O设备的基地址 */
unsigned int irq; /* 设备中断号 */

unsigned char if_port; /* 多端口设备使用哪一个端口*/
unsigned char dma; /* DMA channel

/*设备初始化函数,只被调用一次 */
int (*init)(struct net_device *dev);

/*用于获取网络设备的状态信息*/
struct net_device_stats* (*get_stats)(struct net_device *dev);
 /*存放详细的网络设备流量统计信息*/
struct net_device_stats stats;

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/861c66accdfc15eaae6d77fee967ea7d.html