一、概述
Linux网络设备驱动程序遵循通用的接口,设计时采用的是面向对象的方法,一个设备就是一个对象(net_device结构)。一个网络设备最基本的方法有初始化、发送和接收等。
Linux网络设备驱动程序的体系结构可以分为四层:网络协议接口层、网络设备接口层、设备驱动功能层和网络设备与媒介层,如图1所示。网络设备驱动程序最主要的工作是完成设备驱动功能层。在Linux中,所有网络设备都抽象为一个接口,这个接口提供了对所有网络设备的操作集合。由数据结构struct net_device来表示网络设备在内核中的运行情况,即网络设备接口。它既包括纯软件网络设备接口,如环路(loopback),也包括硬件网络设备接口,如以太网卡。由以dev_base为头指针的设备链来集体管理所有网络设备,该设备链中的每个元素代表一个网络设备接口。数据结构net_device中有很多供系统访问和协议层调用的设备方法,包括初始化,打开和关闭网络设备的open和stop函数,处理数据包发送的hard_start_xmit函数,以及中断处理函数等。
图1 网络设备驱动体系结构
二、数据包发送流程
当网络子系统上层有数据包要发送时,通过调用网络设备驱动中的实现的ndo_start_xmit函数,将要发送的数据包封装在套接字缓冲区skb参数中。在驱动程序的发送数据包函数的具体实现中,它将首先在skb数据包所在主存中的数据块和网络设备内存之间建立一个DMA通道,然后启动该DMA通道将数据包由主存传输到设备内存,之后由网络设备硬件通过网络接口或者天线将数据包发送出去。数据包发送成功后会向处理器发出一个硬件中断,在中断处理程序里做一些善后处理工作,如图2所示。
图2 网络设备驱动程序数据包发送流程
三、数据包接收流程
数据包的接收是一个异步的过程,正因为这样,出于系统性能的考虑,绝大部分网络设备都支持数据接收中断,因此在驱动程序中是通过中断处理程序来接收数据包的。由于系统主存与网络设备之间已经建立好DMA通道,所有当有数据包到达网络设备时,数据包会被自动传输到系统主存,此时将产生一个中断信号,从而进入驱动程序的中断处理函数,在中断处理函数里驱动首先会分配一个套接字缓冲区skb来容纳收到的数据包,然后将skb传递到网络子系统的上层代码中,具体传递的过程是驱动程序通过调用netif_rx(skb)函数实现的,上层代码负责释放该skb所占用的内存,如图3所示。
图3 网络设备驱动数据包接收流程