主要内容:
- 驱动程序数据结构
- 与协议层会话
- 缓冲区管理和并发控制
1.驱动程序数据结构
在为一个NIC写设备驱动程序时,必须操作3个关键数据结构
(1)形成网络协议栈构造块的数据结构。套接字缓冲区,即定义在include/linux/sk_buff.h文件的结构体sk_buff,是内核TCP/IP栈使用的关键结构体。
(2)定义在NIC驱动程序和协议栈接口的数据结构,定义在include/linux/netdevice.h文件中的结构体net_device是构成该接口的核心结构体。
(3)与I/O总线相关的结构体。
1.1 套接字缓冲区
Sk_buff为Linux网络层提供了高效的缓冲区处理和流量控制机制。sk_buff拥有描述对应内存缓冲区的控制信息,sk_buff用5个主要的域将它自身与数据包缓冲区联系起来:
head,用于指向数据包的开始;
data,用于指向数据包载荷的开始
tail,用于指向数据包载荷的结束;
end,用于指向数据包的结束;
len,数据包包含的数据量;
1.2 网络设备接口
NIC驱动程序使用标准接口与TCP/IP协议栈互操作。net_device结构体定义了这个通信接口,下面通过NIC驱动程序初始化步骤,来了解下net_device结构体内部准备:
①驱动程序用alloc_netdev()分配一个net_device结构体,
②驱动程序在分配的net_device中填充多个成员,并用register_netdev(net_dev)向网络层注册net_device
③驱动程序从EEPROM读取NIC的MAC地址
2.与协议层会话
2.1接收数据
(1)在中断模式下,中断处理程序通过调度NET_RX_SOFTIRQ向协议层投递收到的数据包,然后屏蔽NIC中断,接着通过向轮询列表增加设备来切换到轮询模式;
(2)驱动程序通过它的net_device结构体提供一个poll()方法;
(3)在轮询模式下,驱动程序的poll()方法处理接收队列中的数据包,当队列变空时,驱动程序重新启用中断,并通过调用netif_rx_complete()切回到中断模式;
2.2发送数据
协议栈以sk_buff作为输出参数调用驱动程序的hart_start_xmit()方法,驱动程序用DMA方式将数据包数据去除送给NIC,
驱动程序在完成预定数量数据包的传输后,设置NIC向处理器发出中断请求,只有当表示传输操作完成的传输完成中断出现时,驱动程序才能收回或释放资源。
3.缓冲区管理和并发控制
NIC驱动程序维护一个发送和接收DMA描述符的链表,并未缓冲管理执行释放和占用缓冲池。在设备打开期间预分配环形DMA描述和相关的sk_buff;当可用缓冲区低于预定水平线时重组空闲缓冲池;当NIC发送完成时回收用过的缓冲区到空闲池,并接收中断。