Linux 网络类设备不在是基于文件操作(没有对应的映射到文件系统中的设备节点),而是套接字socket来实现通讯
Linux 网络子系统的架构图
各层次接口功能说明:
- 系统调用接口层:为应用程序提供访问网络子系统的统一方法。
- 协议无关层:提供通用的方法来使用传输层协议。
- 协议栈的实现:实现具体的网络协议
- 设备无关层:协议与设备驱动之前通信的通用接口
- 设备驱动程序:
驱动程序数据结构
数据包描述结构:struct sk_buff
-
所在头文件:<linux/sk_buff.h>
-
sk_buff为Linux网络层提供高效的缓冲区处理和流量控制机制,对驱动开发来说比较关心的是sk_buff结构体中的以下数据:
struct sk_buff
{
unsigned int len, /*数据包包含的数据量*/
....
sk_buff_data_t tail; /* 用于指向数据包载荷的结束*/
sk_buff_data_t end; /* 用于指向数据包的结束*/
unsigned char *head; /* 用于指向数据包的开始*/
unsigned char *data; /* 用于指向数据包载荷的开始*/
...
}
网卡描述结构:struct net_device
- 一个网卡结构表示一个具体设备
struct net_device
{
char name[IFNAMSIZ]; /*设备接口名,如eth0 */
...
unsigned long mem_end; /* shared mem end */
unsigned long mem_start; /* shared mem start */
unsigned long base_addr; /* device I/O address */
unsigned int irq; /* device IRQ number */
...
/* Management operations */
const struct net_device_ops *netdev_ops;/*网卡设备操作集*/
const struct ethtool_ops *ethtool_ops;
}
网卡操作描述结构:struct net_device_ops
和字符设备的原理差不多
网卡使用函数
结构分配:
-
alloc_netdev(….):回环网卡分配
-
alloc_ieee80211():WIFI无线网卡分配
-
ndev = alloc_etherdev(sizeof(struct xxx)):对1加工而已,适用于以太网卡
网卡设备注册:
- ret = register_netdev(ndev);
网卡设备注销:
- free_netdev(ndev);
Linux网络设备驱动体系架构分析
设备初始化:
- 申请网络设备:
struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
-
初始化设备dev
-
中断号
-
I/O基地址
-
填充MAC地址(在捕获设备中进行)
-
关联操作函数集:dev->netdev_ops = &net_ops;(捕获设备中进行)
-
-
捕获设备:初始化硬件(或者在open函数中进行)
-
向内核注册网卡驱动:retval = register_netdev(dev);
网卡发送函数:.ndo_start_xmit = net_send_packet,
-
通知上层协议停止发送数据:netif_stop_queue(dev);
-
将skb的数据写入发送寄存器中
-
释放skb空间:dev_kfree_skb (skb);
-
在发送中断处理函数中(网卡有多种类型中断:接收数据包可产生 中断,发送数据包也可以产生中断)通知上层协议可以再次向网卡 传输数据netif_wake_queue(dev);–>唤醒发送队列
网卡接收(在中断中进行):net_rx(struct net_device *dev)
-
读取接收状态
-
读取接收数据长度
-
分配SKB结构:skb = dev_alloc_skb(length + 2); /构造新数据包/
-
从网卡寄存器中读取数据填入SKB结构
-
使用netif_rx(skb);将skb数据包发送给上层协议去处理