第3章讲解了对驱动程序开发有用的一系列内核API。首先介绍了内核线程(它提供了一种在内核空间运行后台任务的能力),接下来讲解了一系列的辅助API(如链表、工作队列、完成函数、通知链等)。这些辅助API能简化代码,剔除内核中的冗余,有助于内核的长期维护。
第4章为掌握Linux设备驱动程序开发艺术打基础。这一章首先呈现一般的PC兼容系统和嵌入式设备的体系结构的鸟瞰图,介绍了设备和驱动程序,并讲解了中断处理和内核设备模型等基本的驱动程序概念。
第5章介绍了Linux字符设备驱动程序的体系架构,引入了几个新概念,譬如轮询、异步通知和I/O控制等。由于本书后面介绍的大多数设备都可以看作“超级”字符设备,所以这些概念也与后续章节密切相关。
第6章讲解了内核串行设备驱动程序的层次结构。
第7章讨论了内核中为键盘、鼠标和触摸屏控制器等输入设备服务的输入子系统。
第8章讲解了通过I2C总线或SMBus总线与系统连接的设备(如EEPROM)的驱动程序,同时也介绍了SPI总线和1-wire总线等其他串行接口。
第9章分析了PCMCIA子系统,讲授了如何编写含PCMCIA或CF组件的设备的驱动程序。
第10章描述了内核对PCI及其衍生总线设备的支持。
第11章探讨了USB的体系架构,并讲解了如何利用Linux内核USB子系统的API来开发USB设备驱动程序。
.第12章讲解了Linux视频子系统,分析了内核提供的帧缓冲结构的优点,并给出了帧缓冲设备驱动程序的编写方法。
第13章描述了Linux音频子系统的架构,并给出了音频设备驱动程序的实现方法。
第14章集中描述存储设备(如硬盘)的驱动程序,并介绍Linux块子系统所支持的几种不同的I/O调度策略。
第15章分析了网络设备驱动程序,介绍内核中与网络相关的数据结构以及网络设备驱动程序与协议层接口的实现方法。
第16章描述了各种无线网络设备的驱动程序,如蓝牙、红外、无线局域网WiFi和蜂窝通信等。
第17章讲解了如何让闪存在嵌入式设备上运行起来linux 常用命令,这一章最后讲解了PC上的FWH(FirmWare Hub,固件集线器)的驱动程序。
第18章介绍了嵌入式Linux,包括嵌入式设备中的引导装入程序、内核以及设备驱动程序等主要的固件组成。由于Linux在嵌入式领域越来越受欢迎,本书中介绍的Linux驱动程序开发技能极有可能应用于嵌入式领域。
第19章讲解了如何在用户空间驱动各种设备。一些设备驱动程序(尤其是那些重策略、轻性能的设备)更适合在用户空间被驱动。这一章也分析了Linux进程调度对用户空间设备驱动程序响应时间的影响。
第20章描述了之前尚未论及的设备驱动程序系统,如错误侦测和校验(EDAC)、火线接口以及ACPI等。
第21章讲解了用来调试Linux内核代码的各种调试工具,包括跟踪工具、内核探测器、崩溃转储和性能剖析器的使用方法。在开发Linux驱动程序的时候就可用到本章所学的驱动调试技能。
第22章给出了设备驱动程序软件开发生命周期的概况。
第23章给出了当开始进行一个新设备驱动程序开发工作时,应该查验的工作项目清单。本书最后是对“下一步该做什么”的思考。
设备驱动程序中有时候需要以汇编语言实现一些代码片段,因此,附录A介绍了Linux汇编编程的一些内容。x86系统上的一些设备驱动程序直接或间接地依赖于BIOS,因此,附录B讲解了Linux如何与BIOS交互。附录C描述了2.6内核提供的seq文件,它是用于监控和追踪数据点的辅助接口。
本书大体上根据设备和总线的复杂度进行组织linux 软件,同时也结合了章与章之间互相关联的客观情况。我们从讲解基本的设备类型开始(如字符设备、串口和输入设备),紧接着介绍简单的串行总线(如I2C和SMBus),之后介绍PCMCIA、PCI和USB等外部I/O总线。由于视频、音频、块和网络设备通常通过这些I/O总线与处理器连接,因此在介绍完这些总线之后,还讲解了这些设备的驱动程序。之后面向嵌入式Linux,讲述了无线连网和闪存等技术。最后讨论了用户空间的设备驱动程序。
内核版本
本书总体上紧跟2.6.23/2.6.24内核版本,书中列出的大部分代码都在2.6.23上测试过。如果读者使用的是更新的版本,请通过类似的Linux网站了解内核自2.6.23/2.6.24后进行了哪些更改。
本书网站
我特意建立了网站,提供与本书相关的更新和勘误等信息。
本书约定
源代码、函数名和shell命令使用代码体。shell提示符为bash]。新名词使用楷体表示。
为了实现代码示例linux usb驱动程序开发linux usb驱动程序开发,一些章节修改了原始的内核源代码。为标识出这些修改,新添加的代码前添加了+,删除的代码前则添加了。
为简单起见,本书有时使用了通用的路径名。因此,当遇到arch/your-arch/目录时,应该根据当前的编译情况进行转换。例如,如果你正在为x86体系结构编译内核,它应该转换为arch/x86/。类似地,如果你正在为ARM体系结构编译内核,include/asm-your-arch/就应该转换为include/asm-arm/。本书偶尔在文件名中使用*和X作为通配符。因此,如果书中要求查看include/linux/time*.h文件,读者就应该查看include/linux/下的time.h、timer.h、times.h和timex.h所有这些头文件。同样地,如果书中包含类似/dev/input/eventX或/sys/devices/platform/i8042/serioX/这样的文件名,要知道其中的X是指在当前系统配置情况下内核分配给设备的接口号。
→符号有时候会插入在命令或内核的输出之间,目的是附加注释。
为了紧凑地列出函数原型,本书偶尔使用了一些简单的正则表达式。例如,在10.4节中就用pci_[map