基于USB设备的Linux网络驱动程序开发
做为开放源代码 (Open Source) 运动重要组成部分,Linux操作系统吸引了数以万计的程序员共同开发。由于Linux比较完整的继承了各种UNIX版本的稳定和高效,并且克服和改进了传统UNIX中的很多缺点,更因为其开放的开发模式,Linux成为一个具有强大网络服务功能的操作系统。它支持主流的TCP/IP以及IPX/SPX、 NETBEUI等众多网络协议,无论在嵌入式系统,服务器还是桌面操作系统领域,Linux都取得了广泛的应用。网络驱动程序和网络硬件设备实现网络协议栈中的数据链路层和物理层,对上层协议提供支持,是网络协议栈的重要组成部分,对Linux的网络性能起着决定作用。本文主要讨论基于USB总线的 Linux网络驱动程序的设计和实现方法。
2. Linux体系结构
出于稳定性和安全性的考虑,现代处理器往往具有至少两个运行级别。权限较低的级别无法访问所有的寄存器,不能对硬件直接操作。而权限较高的级别能够进行所有的硬件操作和访问任何系统资源。Linux设计充分利用了现代处理器的上述特性,其内核部分运行于高权限级别,应用程序运行于低权限级别。作为宏内核结构的操作系统,Linux将进程管理、内存管理、网络协议栈、设备驱动和文件系统等服务都集成在内核中,而应用程序则通过系统调用与内核通讯,内核结构如图1所示。
图1
图2
Linux网络子系统基本可以分为系统调用接口、BSD套接字、INET套接字、TCP/IP以及数据链路层。其中,BSD套接字由INET套接字层提供支持,而INET套接字管理着基于IP的TCP或UDP协议端,实现IP分组排序以及控制网络子系统效率等功能。各种网络驱动程序位于IP层之下,它们具有访问硬件设备的能力,实现数据链路层的功能。网络子系统的结构如图2所示。
3. Linux网络驱动程序结构
一个完整的驱动程序是一组回调(Callback)函数的集合。内核根据用户或自身的需要来调用驱动程序提供的函数指针,将控制或数据请求交给相应的驱动程序。驱动程序负责了解相应硬件设备的访问和控制方式,将内核的请求翻译成设备可以理解的操作。这样的层次结构使得内核不必了解硬件设备的访问机制和细节,驱动程序也无需明白内核的控制策略,大大提高了驱动程序的兼容性,同时也方便了程序的调试。根据驱动程序类型的不同,内核要求驱动程序提供的回调函数也不同。
Linux下的Ethernet驱动程序需要注册的回调函数分为“必要”和“可选”两类。“必要”的回调函数是指一个Ethernet驱动程序正常工作所需要的回调函数最小集合,而“可选”的回调函数则是在“必要”的基础上提供更丰富的特性和功能。“必要”的回调函数如表1所示。
函数名称 | 功能 |
open | 打开网络接口;将硬件设备配置为正常工作状态。 |
stop | 关闭网络接口;停止硬件设备工作,释放打开该接口时分配的系统资源。 |
tx_timeout | 当上层协议认为某个数据包发送超时的时候调用;该函数应该解决数据包发送超时问题,并保证函数返回以后,数据包能够正常发送。 |
hard_start_xmit | 由上层协议在希望发送数据包时调用;将来自上层协议的数据包转换为硬件设备能够处理的格式,发送至硬件设备。 |
get_stats | 当上层希望了解驱动程序控制的网络设备的统计信息的时候被调用。 |
hard_header | 根据网络子系统先前地址解析的结果,构造数据包的硬件包头。 |
rebuild_header | 在ARP解析完成之后,由上层协议在发送任何新数据包之间调用,重新构造硬件包头。 |
set_config | 改变网络接口的配置,例如中断号和I/O地址等。 |
表1
为了方便Ethernet驱动程序的设计,Linux内核为hard_header、rebuild_header和set_config提供了通用的回调函数。如果对硬件包头或设备配置没有特殊的要求,通用的回调函数就能够满足网络子系统的要求。
4. 基于USB总线的Linux网络驱动程序设计
4.1 USB设备的访问和控制
与PCI、ISA等设备不同,USB、1394等新一代总线没有IO/MEM映射、中断和DMA硬件资源。取而代之的,是抽象出来的硬件资源概念。对于USB设备来说,资源主要包括配置(configuration)、接口(interface)和端点(endpoint)。三者之间的关系如图3所示。
linux操作系统文章专题:linux操作系统详解(linux不再难懂)
评论