Linux网络设备驱动
linux网络设备驱动体系结构
Linux网络设备驱动程序的体系结构可分为4层,依次为网络协议接口层、网络设备接口层、提供实际功能的设备驱动功能层和网络设备与媒介层。如下所示。
网络协议接口层
网络协议接口层的功能主要是给上层提供透明的数据包发送和接收接口。其接口如下:
1 | int dev_queue_xmit(struct sk_buff *skb); |
与收发接口紧密联系的是sk_buff这个结构,这是用于描述网络数据的缓存结构,它在Linux网络子系统中的各层之间传递数据,是各层之间数据传输的标准形式。sk_buff中包含4个指针成员:head、data、tail、end共同用来描述网络数据所占的内存区域。如下图所示。
对于skb_buff数据结构的操作函数有如下这些:
1 | /* sk_buff的申请与释放 */ |
网络设备接口层
网络设备接口层的主要功能是为各种各样的网络设备定义统一、抽象的数据结构net_device结构体,实现各种硬件在软件层次上的统一。
net_device在内核中指代一个网络设备,有了这个定义,网络设备驱动之需要填充net_device的具体成员并注册即可实现硬件操作函数与内核的挂接。
设备操作函数
1 | const struct net_device_ops *netdev_ops; |
该结构体是网络设备的一系列硬件操作行为的结合,它定义了init,open,close等一系列硬件操作接口。
除了netdev_ops外,在net_device中还存在类似于ethtool_ops、header_ops这样的操作集:
1 | const struct ethtool_ops *ethtool_ops; |
ethtool_ops成员函数于用户空间ethtool工具的各个命令选项对应,ethtool提供了网卡及网卡驱动管理能力,能够为linux网络开发人员和管理人员提供对网卡硬件、驱动程序和网络协议栈的设置、查看和调试等功能。
header_ops对应于硬件头部操作,主要是完成创建硬件头部和给定的sk_buff分析出硬件头部等操作。
辅助成员
1 | unsigned long trans_start; |
trans_start记录最后的数据包开始发送时的时间戳,state记录最后一次接收到数据包时的时间戳,这两个时间戳记录的都是jiffies,驱动程序应维护这两个成员。
通常情况下,网络设备驱动以中断方式接收数据包,而poll_controller()则采用纯轮询方式,另外一种数据接收方式是NAPI(New API),其数据接收流程为“接收中断来临->关闭接收中断->以轮询方式接收所有数据包直到为空->开启接收中断->接收中断来临……”
内核中提供了如下NAPI的API。
1 | /* 初始化与移除napi */ |
设备驱动功能层
net_device结构体的成员需要被设备驱动功能层赋予具体的数值和函数。对于具体的设备xxx,应该标写相应的设备驱动功能层的函数,这些函数形如xxx_open()、xxx_stop()、xxx_tx()等。
由于网络数据包的接收可由中断引发,设备驱动功能层的另一个主体部分将是中断处理函数,它负责读取硬件上接收到的数据包并传送给上层协议。
具体的网络设备驱动设计通常要实现如下部分:
- 网络设备驱动的注册与注销
- 网络设备的初始化
- 网络设备的打开与释放
- 数据发送
- 数据接收
- 网络连接状态
- 参数设置和统计数据
对于一个完整的网络设备驱动其实现可参考drivers/net/ethernet/3com/3c509.c
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 yxhlfx@163.com
文章标题:Linux网络设备驱动
本文作者:红尘追风
发布时间:2016-09-01, 15:12:43
原始链接:http://www.micernel.com/2016/09/01/Linux%E7%BD%91%E7%BB%9C%E8%AE%BE%E5%A4%87%E9%A9%B1%E5%8A%A8/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。