http://www.china-pub.com/196419
——Theodore Ts’o,Linux基金会首席平台战略师,北美第一位内核开发者
“我要找的就是这样一本书,它告诉我的不只是实例,更重要的是设备驱动程序的设计思路。”
—— Anthony Lawrence,知名操作系统咨询师
精通Linux 设备驱动程序开发
| |
基本信息
- 作者: (印)Sreekrishnan Venkateswaran [作译者介绍]
- 译者: 宋宝华;何昭然;史海滨;吴国成[同译者作品]
- 丛书名: 图灵程序设计丛书
- 出版社:人民邮电出版社
- ISBN:9787115221674
- 上架时间:2010-2-26
- 出版日期:2010 年3月
- 开本:16开
- 页码:1
- 版次:1-1
- 所属分类: 计算机 > 操作系统 >
Linux
内容简介
本书是Linux 设备驱动程序开发领域的权威著作。全书基于2.6 内核,不仅透彻讲解了基本概念和技术,更深入探讨了其他书没有涵盖或浅尝辄止的许多重要主题和关键难点,如PCMCIA、I2C 和USB 等外部总线以及视频、音频、无线连网和闪存等驱动程序的开发,并讲解了相关的内核源码文件,给出了完整的开发实例。
本书适合中高级Linux 开发人员阅读。
本书适合中高级Linux 开发人员阅读。
作译者
本书提供作译者介绍
Sreekrishnan Venkateswaran 世界顶级Linux开发技术专家。在IBM工作多年,有丰富的嵌入式Linux和驱动程序开发经验,曾经将Linux移植到了手表、音乐播放器、VoIP 电话、心脏起搏器以及远程门诊监控系统等设备上。目前负责IBM印度公司的嵌入式解决方案组。他曾担任Linux Magazine的特邀编辑,主持内核技术专栏。
.. << 查看详细
.. << 查看详细
目录
第1章 引言 1
1.1 演进 1
1.2 GNU Copyleft 2
1.3 kernel.org 2
1.4 邮件列表和论坛 3
1.5 Linux发行版 3
1.6 查看源代码 4
1.7 编译内核 7
1.8 可加载的模块 8
1.9 整装待发 9
第2章 内核 11
2.1 启动过程 11
2.1.1 BIOS-provided physical RAM map 12
2.1.2 758MB LOWMEM available 14
2.1.3 Kernel command line: ro
root=/dev/hda1 14
2.1.4 Calibrating delay...1197.46BogoMIPS (lpj=2394935) 15
2.1.5 Checking HLT instruction 16
2.1.6 NET: Registered protocol family 2 17
2.1.7 Freeing initrd memory: 387k freed 17
1.1 演进 1
1.2 GNU Copyleft 2
1.3 kernel.org 2
1.4 邮件列表和论坛 3
1.5 Linux发行版 3
1.6 查看源代码 4
1.7 编译内核 7
1.8 可加载的模块 8
1.9 整装待发 9
第2章 内核 11
2.1 启动过程 11
2.1.1 BIOS-provided physical RAM map 12
2.1.2 758MB LOWMEM available 14
2.1.3 Kernel command line: ro
root=/dev/hda1 14
2.1.4 Calibrating delay...1197.46BogoMIPS (lpj=2394935) 15
2.1.5 Checking HLT instruction 16
2.1.6 NET: Registered protocol family 2 17
2.1.7 Freeing initrd memory: 387k freed 17
.2.1.8 io scheduler anticipatory registered (default) 18
2.1.9 Setting up standard PCI resources 18
2.1.10 EXT3-fs: mounted filesystem 19
2.1.11 INIT: version 2.85 booting 19
2.2 内核模式和用户模式 20
2.3 进程上下文和中断上下文 20
2.4 内核定时器 21
2.4.1 HZ和Jiffies 21
2.4.2 长延时 22
2.4.3 短延时 24
2.4.4 Pentium时间戳计数器 24
2.4.5 实时钟 25
2.5 内核中的并发 26
2.5.1 自旋锁和互斥体 26
2.5.2 原子操作 30
2.5.3 读—写锁 31
2.5.4 调试 32
2.6 proc文件系统 32
2.7 内存分配 33
2.8 查看源代码 34
第3章 内核组件 37
3.1 内核线程 37
3.1.1 创建内核线程 37
3.1.2 进程状态和等待队列 41
3.1.3 用户模式辅助程序 42
3.2 辅助接口 43
3.2.1 链表 44
3.2.2 散列链表 49
3.2.3 工作队列 49
3.2.4 通知链 51
3.2.5 完成接口 54
3.2.6 kthread辅助接口 56
3.2.7 错误处理助手 57
3.3 查看源代码 58
第4章 基本概念 61
4.1 设备和驱动程序介绍 61
4.2 中断处理 63
4.2.1 中断上下文 63
4.2.2 分配IRQ号 64
4.2.3 设备实例:导航杆 65
4.2.4 softirq和tasklet 68
4.3 Linux设备模型 71
4.3.1 udev 71
4.3.2 sysfs、kobject和设备类 73
4.3.3 热插拔和冷插拔 76
4.3.4 微码下载 76
4.3.5 模块自动加载 77
4.4 内存屏障 78
4.5 电源管理 79
4.6 查看源代码 79
第5章 字符设备驱动程序 81
5.1 字符设备驱动程序基础 81
5.2 设备实例:系统CMOS 82
5.2.1 驱动程序初始化 83
5.2.2 打开与释放 86
5.2.3 数据交换 88
5.2.4 查找 92
5.2.5 控制 94
5.3 检测数据可用性 95
5.3.1 轮询 95
5.3.2 Fasync 98
5.4 和并行端口交互 99
5.5 RTC子系统 108
5.6 伪字符驱动程序 109
5.7 混杂驱动程序 110
5.8 字符设备驱动程序警告 115
5.9 查看源代码 115
第6章 串行设备驱动程序 118
6.1 层次架构 119
6.2 UART驱动程序 121
6.2.1 设备实例:手机 122
6.2.2 RS-485 132
6.3 TTY驱动程序 132
6.4 线路规程 134
6.5 查看源代码 141
第7章 输入设备驱动程序 143
7.1 输入事件驱动程序 144
7.2 输入设备驱动程序 150
7.2.1 serio 150
7.2.2 键盘 150
7.2.3 鼠标 152
7.2.4 触摸控制器 157
7.2.5 加速度传感器 158
7.2.6 输出事件 158
7.3 调试 159
7.4 查看源代码 160
第8章 I2C协议 161
8.1 I2C/SMBus是什么 161
8.2 I2C核心 162
8.3 总线事务 164
8.4 设备实例:EEPROM 164
8.4.1 初始化 165
8.4.2 探测设备 167
8.4.3 检查适配器的功能 169
8.4.4 访问设备 169
8.4.5 其他函数 170
8.5 设备实例:实时时钟 171
8.6 i2c-dev 174
8.7 使用LM-Sensors监控硬件 174
8.8 SPI总线 174
8.9 1-Wire总线 176
8.10 调试 176
8.11 查看源代码 176
第9章 PCMCIA和CF 179
9.1 PCMCIA/CF是什么 179
9.2 Linux-PCMCIA子系统 181
9.3 主机控制器驱动程序 183
9.4 PCMCIA核心 183
9.5 驱动程序服务 183
9.6 客户驱动程序 183
9.6.1 数据结构 184
9.6.2 设备实例:PCMCIA卡 185
9.7 将零件组装在一起 188
9.8 PCMCIA存储 189
9.9 串行PCMCIA 189
9.10 调试 191
9.11 查看源代码 191
第10章 PCI 193
10.1 PCI系列 193
10.2 寻址和识别 195
10.3 访问PCI 198
10.3.1 配置区 198
10.3.2 I/O和内存 199
10.4 DMA 200
10.5 设备实例:以太网—调制解调器卡 203
10.5.1 初始化和探测 203
10.5.2 数据传输 209
10.6 调试 214
10.7 查看源代码 214
第11章 USB 216
11.1 USB体系架构 216
11.1.1 总线速度 218
11.1.2 主机控制器 218
11.1.3 传输模式 219
11.1.4 寻址 219
11.2 Linux-USB子系统 220
11.3 驱动程序的数据结构 221
11.3.1 usb_device结构体 221
11.3.2 URB 222
11.3.3 管道 223
11.3.4 描述符结构 223
11.4 枚举 225
11.5 设备实例:遥测卡 225
11.5.1 初始化和探测过程 226
11.5.2 卡寄存器的访问 230
11.5.3 数据传输 233
11.6 类驱动程序 236
11.6.1 大容量存储设备 236
11.6.2 USB-串行端口转换器 241
11.6.3 人机接口设备 243
11.6.4 蓝牙 243
11.7 小配件驱动程序 243
11.8 调试 244
11.9 查看源代码 245
第12章 视频驱动程序 247
12.1 显示架构 247
12.2 Linux视频子系统 249
12.3 显示参数 251
12.4 帧缓冲API 252
12.5 帧缓冲驱动程序 254
12.6 控制台驱动程序 265
12.6.1 设备实例:手机 266
12.6.2 启动logo 270
12.7 调试 270
12.8 查看源代码 271
第13章 音频驱动程序 273
13.1 音频架构 273
13.2 Linux声音子系统 275
13.3 设备实例:MP3播放器 277
13.3.1 驱动程序函数和结构体 278
13.3.2 ALSA编程 287
13.4 调试 288
13.5 查看源代码 289
第14章 块设备驱动程序 291
14.1 存储技术 291
14.2 Linux块I/O层 295
14.3 I/O调度器 295
14.4 块驱动程序数据结构和方法 296
14.5 设备实例:简单存储控制器 298
14.5.1 初始化 299
14.5.2 块设备操作 301
14.5.3 磁盘访问 302
14.6 前沿内容 304
14.7 调试 306
14.8 查看源代码 306
第15章 网络接口卡 308
15.1 驱动程序数据结构 308
15.1.1 套接字缓冲区 309
15.1.2 网络设备接口 310
15.1.3 激活 311
15.1.4 数据传输 311
15.1.5 看门狗 311
15.1.6 统计 312
15.1.7 配置 313
15.1.8 总线相关内容 314
15.2 与协议层会话 314
15.2.1 接收路径 314
15.2.2 传输路径 315
15.2.3 流量控制 315
15.3 缓冲区管理和并发控制 315
15.4 设备实例:以太网NIC 316
15.5 ISA网络驱动程序 321
15.6 ATM 321
15.7 网络吞吐量 322
15.7.1 驱动程序性能 322
15.7.2 协议性能 323
15.8 查看源代码 324
第16章 Linux无线设备驱动 326
16.1 蓝牙 327
16.1.1 BlueZ 328
16.1.2 设备实例:CF卡 329
16.1.3 设备实例:USB适配器 330
16.1.4 RFCOMM 331
16.1.5 网络 332
16.1.6 HID 334
16.1.7 音频 334
16.1.8 调试 334
16.1.9 关于源代码 334
16.2 红外 335
16.2.1 Linux-IrDA 335
16.2.2 设备实例:超级I/O芯片 337
16.2.3 设备实例:IR软件狗 338
16.2.4 IrCOMM 340
16.2.5 联网 340
16.2.6 IrDA套接字 341
16.2.7 LIRC 341
16.2.8 关于源代码 342
16.3 WiFi 343
16.3.1 配置 343
16.3.2 设备驱动程序 346
16.3.3 关于源代码 347
16.4 蜂窝网络 347
16.4.1 GPRS 347
16.4.2 CDMA 349
16.5 当前趋势 350
第17章 存储技术设备 352
17.1 什么是闪存 352
17.2 Linux-MTD子系统 353
17.3 映射驱动程序 353
17.4 NOR芯片驱动程序 358
17.5 NAND芯片驱动程序 359
17.6 用户模块 361
17.6.1 块设备模拟 361
17.6.2 字符设备模拟 361
17.6.3 JFFS2 362
17.6.4 YAFFS2 363
17.7 MTD工具 363
17.8 配置MTD 363
17.9 XIP 364
17.10 FWH 364
17.11 调试 367
17.12 查看源代码 367
第18章 嵌入式Linux 369
18.1 挑战 369
18.2 元器件选择 370
18.3 工具链 371
18.4 嵌入式引导装入程序 372
18.5 内存布局 374
18.6 内核移植 375
18.7 嵌入式驱动程序 376
18.7.1 闪存 377
18.7.2 UART 377
18.7.3 按钮和滚轮 378
18.7.4 PCMCIA/CF 378
18.7.5 SD/MMC 378
18.7.6 USB 378
18.7.7 RTC 378
18.7.8 音频 378
18.7.9 触摸屏 379
18.7.10 视频 379
18.7.11 CPLD/FPGA 379
18.7.12 连接性 379
18.7.13 专用领域电子器件 380
18.7.14 更多驱动程序 380
18.8 根文件系统 380
18.8.1 NFS挂载的根文件系统 381
18.8.2 紧凑型中间件 382
18.9 测试基础设施 383
18.10 调试 383
18.10.1 电路板返工 384
18.10.2 调试器 385
第19章 用户空间的驱动程序 386
19.1 进程调度和响应时间 387
19.1.1 原先的调度器 387
19.1.2 O(1)调度器 387
19.1.3 CFS 388
19.1.4 响应时间 388
19.2 访问I/O区域 390
19.3 访问内存区域 393
19.4 用户模式SCSI 395
19.5 用户模式USB 397
19.6 用户模式I2C 400
19.7 UIO 401
19.8 查看源代码 402
第20章 其他设备和驱动程序 403
20.1 ECC报告 403
20.2 频率调整 407
20.3 嵌入式控制器 408
20.4 ACPI 408
20.5 ISA与MCA 410
20.6 火线 410
20.7 智能输入/输出 411
20.8 业余无线电 411
20.9 VoIP 411
20.10 高速互联 412
20.10.1 InfiniBand 413
20.10.2 RapidIO 413
20.10.3 光纤通道 413
20.10.4 iSCSI 413
第21章 调试设备驱动程序 414
21.1 kdb 414
21.1.1 进入调试器 415
21.1.2 kdb 415
21.1.3 kgdb 417
21.1.4 gdb 420
21.1.5 JTAG调试器 421
21.1.6 下载 423
21.2 内核探测器 423
21.2.1 kprobe 423
21.2.2 jprobe 427
21.2.3 返回探针 429
21.2.4 局限性 431
21.2.5 查看源代码 431
21.3 kexec与kdump 431
21.3.1 kexec 432
21.3.2 kdump与kexec协同工作 432
21.3.3 kdump 433
21.3.4 查看源代码 437
21.4 性能剖析 437
21.4.1 利用OProfile剖析内核性能 438
21.4.2 利用gprof剖析应用程序性能 440
21.5 跟踪 441
21.6 LTP 444
21.7 UML 444
21.8 诊断工具 444
21.9 内核修改配置选项 444
21.10 测试设备 445
第22章 维护与发布 446
22.1 代码风格 446
22.2 修改标记 446
22.3 版本控制 447
22.4 一致性检查 447
22.5 构建脚本 448
22.6 可移植代码 450
第23章 结束语 451
23.1 流程一览表 451
23.2 下一步该做什么 452
附录A Linux汇编 453
附录B Linux与BIOS 457
附录C seq文件 461
2.1.9 Setting up standard PCI resources 18
2.1.10 EXT3-fs: mounted filesystem 19
2.1.11 INIT: version 2.85 booting 19
2.2 内核模式和用户模式 20
2.3 进程上下文和中断上下文 20
2.4 内核定时器 21
2.4.1 HZ和Jiffies 21
2.4.2 长延时 22
2.4.3 短延时 24
2.4.4 Pentium时间戳计数器 24
2.4.5 实时钟 25
2.5 内核中的并发 26
2.5.1 自旋锁和互斥体 26
2.5.2 原子操作 30
2.5.3 读—写锁 31
2.5.4 调试 32
2.6 proc文件系统 32
2.7 内存分配 33
2.8 查看源代码 34
第3章 内核组件 37
3.1 内核线程 37
3.1.1 创建内核线程 37
3.1.2 进程状态和等待队列 41
3.1.3 用户模式辅助程序 42
3.2 辅助接口 43
3.2.1 链表 44
3.2.2 散列链表 49
3.2.3 工作队列 49
3.2.4 通知链 51
3.2.5 完成接口 54
3.2.6 kthread辅助接口 56
3.2.7 错误处理助手 57
3.3 查看源代码 58
第4章 基本概念 61
4.1 设备和驱动程序介绍 61
4.2 中断处理 63
4.2.1 中断上下文 63
4.2.2 分配IRQ号 64
4.2.3 设备实例:导航杆 65
4.2.4 softirq和tasklet 68
4.3 Linux设备模型 71
4.3.1 udev 71
4.3.2 sysfs、kobject和设备类 73
4.3.3 热插拔和冷插拔 76
4.3.4 微码下载 76
4.3.5 模块自动加载 77
4.4 内存屏障 78
4.5 电源管理 79
4.6 查看源代码 79
第5章 字符设备驱动程序 81
5.1 字符设备驱动程序基础 81
5.2 设备实例:系统CMOS 82
5.2.1 驱动程序初始化 83
5.2.2 打开与释放 86
5.2.3 数据交换 88
5.2.4 查找 92
5.2.5 控制 94
5.3 检测数据可用性 95
5.3.1 轮询 95
5.3.2 Fasync 98
5.4 和并行端口交互 99
5.5 RTC子系统 108
5.6 伪字符驱动程序 109
5.7 混杂驱动程序 110
5.8 字符设备驱动程序警告 115
5.9 查看源代码 115
第6章 串行设备驱动程序 118
6.1 层次架构 119
6.2 UART驱动程序 121
6.2.1 设备实例:手机 122
6.2.2 RS-485 132
6.3 TTY驱动程序 132
6.4 线路规程 134
6.5 查看源代码 141
第7章 输入设备驱动程序 143
7.1 输入事件驱动程序 144
7.2 输入设备驱动程序 150
7.2.1 serio 150
7.2.2 键盘 150
7.2.3 鼠标 152
7.2.4 触摸控制器 157
7.2.5 加速度传感器 158
7.2.6 输出事件 158
7.3 调试 159
7.4 查看源代码 160
第8章 I2C协议 161
8.1 I2C/SMBus是什么 161
8.2 I2C核心 162
8.3 总线事务 164
8.4 设备实例:EEPROM 164
8.4.1 初始化 165
8.4.2 探测设备 167
8.4.3 检查适配器的功能 169
8.4.4 访问设备 169
8.4.5 其他函数 170
8.5 设备实例:实时时钟 171
8.6 i2c-dev 174
8.7 使用LM-Sensors监控硬件 174
8.8 SPI总线 174
8.9 1-Wire总线 176
8.10 调试 176
8.11 查看源代码 176
第9章 PCMCIA和CF 179
9.1 PCMCIA/CF是什么 179
9.2 Linux-PCMCIA子系统 181
9.3 主机控制器驱动程序 183
9.4 PCMCIA核心 183
9.5 驱动程序服务 183
9.6 客户驱动程序 183
9.6.1 数据结构 184
9.6.2 设备实例:PCMCIA卡 185
9.7 将零件组装在一起 188
9.8 PCMCIA存储 189
9.9 串行PCMCIA 189
9.10 调试 191
9.11 查看源代码 191
第10章 PCI 193
10.1 PCI系列 193
10.2 寻址和识别 195
10.3 访问PCI 198
10.3.1 配置区 198
10.3.2 I/O和内存 199
10.4 DMA 200
10.5 设备实例:以太网—调制解调器卡 203
10.5.1 初始化和探测 203
10.5.2 数据传输 209
10.6 调试 214
10.7 查看源代码 214
第11章 USB 216
11.1 USB体系架构 216
11.1.1 总线速度 218
11.1.2 主机控制器 218
11.1.3 传输模式 219
11.1.4 寻址 219
11.2 Linux-USB子系统 220
11.3 驱动程序的数据结构 221
11.3.1 usb_device结构体 221
11.3.2 URB 222
11.3.3 管道 223
11.3.4 描述符结构 223
11.4 枚举 225
11.5 设备实例:遥测卡 225
11.5.1 初始化和探测过程 226
11.5.2 卡寄存器的访问 230
11.5.3 数据传输 233
11.6 类驱动程序 236
11.6.1 大容量存储设备 236
11.6.2 USB-串行端口转换器 241
11.6.3 人机接口设备 243
11.6.4 蓝牙 243
11.7 小配件驱动程序 243
11.8 调试 244
11.9 查看源代码 245
第12章 视频驱动程序 247
12.1 显示架构 247
12.2 Linux视频子系统 249
12.3 显示参数 251
12.4 帧缓冲API 252
12.5 帧缓冲驱动程序 254
12.6 控制台驱动程序 265
12.6.1 设备实例:手机 266
12.6.2 启动logo 270
12.7 调试 270
12.8 查看源代码 271
第13章 音频驱动程序 273
13.1 音频架构 273
13.2 Linux声音子系统 275
13.3 设备实例:MP3播放器 277
13.3.1 驱动程序函数和结构体 278
13.3.2 ALSA编程 287
13.4 调试 288
13.5 查看源代码 289
第14章 块设备驱动程序 291
14.1 存储技术 291
14.2 Linux块I/O层 295
14.3 I/O调度器 295
14.4 块驱动程序数据结构和方法 296
14.5 设备实例:简单存储控制器 298
14.5.1 初始化 299
14.5.2 块设备操作 301
14.5.3 磁盘访问 302
14.6 前沿内容 304
14.7 调试 306
14.8 查看源代码 306
第15章 网络接口卡 308
15.1 驱动程序数据结构 308
15.1.1 套接字缓冲区 309
15.1.2 网络设备接口 310
15.1.3 激活 311
15.1.4 数据传输 311
15.1.5 看门狗 311
15.1.6 统计 312
15.1.7 配置 313
15.1.8 总线相关内容 314
15.2 与协议层会话 314
15.2.1 接收路径 314
15.2.2 传输路径 315
15.2.3 流量控制 315
15.3 缓冲区管理和并发控制 315
15.4 设备实例:以太网NIC 316
15.5 ISA网络驱动程序 321
15.6 ATM 321
15.7 网络吞吐量 322
15.7.1 驱动程序性能 322
15.7.2 协议性能 323
15.8 查看源代码 324
第16章 Linux无线设备驱动 326
16.1 蓝牙 327
16.1.1 BlueZ 328
16.1.2 设备实例:CF卡 329
16.1.3 设备实例:USB适配器 330
16.1.4 RFCOMM 331
16.1.5 网络 332
16.1.6 HID 334
16.1.7 音频 334
16.1.8 调试 334
16.1.9 关于源代码 334
16.2 红外 335
16.2.1 Linux-IrDA 335
16.2.2 设备实例:超级I/O芯片 337
16.2.3 设备实例:IR软件狗 338
16.2.4 IrCOMM 340
16.2.5 联网 340
16.2.6 IrDA套接字 341
16.2.7 LIRC 341
16.2.8 关于源代码 342
16.3 WiFi 343
16.3.1 配置 343
16.3.2 设备驱动程序 346
16.3.3 关于源代码 347
16.4 蜂窝网络 347
16.4.1 GPRS 347
16.4.2 CDMA 349
16.5 当前趋势 350
第17章 存储技术设备 352
17.1 什么是闪存 352
17.2 Linux-MTD子系统 353
17.3 映射驱动程序 353
17.4 NOR芯片驱动程序 358
17.5 NAND芯片驱动程序 359
17.6 用户模块 361
17.6.1 块设备模拟 361
17.6.2 字符设备模拟 361
17.6.3 JFFS2 362
17.6.4 YAFFS2 363
17.7 MTD工具 363
17.8 配置MTD 363
17.9 XIP 364
17.10 FWH 364
17.11 调试 367
17.12 查看源代码 367
第18章 嵌入式Linux 369
18.1 挑战 369
18.2 元器件选择 370
18.3 工具链 371
18.4 嵌入式引导装入程序 372
18.5 内存布局 374
18.6 内核移植 375
18.7 嵌入式驱动程序 376
18.7.1 闪存 377
18.7.2 UART 377
18.7.3 按钮和滚轮 378
18.7.4 PCMCIA/CF 378
18.7.5 SD/MMC 378
18.7.6 USB 378
18.7.7 RTC 378
18.7.8 音频 378
18.7.9 触摸屏 379
18.7.10 视频 379
18.7.11 CPLD/FPGA 379
18.7.12 连接性 379
18.7.13 专用领域电子器件 380
18.7.14 更多驱动程序 380
18.8 根文件系统 380
18.8.1 NFS挂载的根文件系统 381
18.8.2 紧凑型中间件 382
18.9 测试基础设施 383
18.10 调试 383
18.10.1 电路板返工 384
18.10.2 调试器 385
第19章 用户空间的驱动程序 386
19.1 进程调度和响应时间 387
19.1.1 原先的调度器 387
19.1.2 O(1)调度器 387
19.1.3 CFS 388
19.1.4 响应时间 388
19.2 访问I/O区域 390
19.3 访问内存区域 393
19.4 用户模式SCSI 395
19.5 用户模式USB 397
19.6 用户模式I2C 400
19.7 UIO 401
19.8 查看源代码 402
第20章 其他设备和驱动程序 403
20.1 ECC报告 403
20.2 频率调整 407
20.3 嵌入式控制器 408
20.4 ACPI 408
20.5 ISA与MCA 410
20.6 火线 410
20.7 智能输入/输出 411
20.8 业余无线电 411
20.9 VoIP 411
20.10 高速互联 412
20.10.1 InfiniBand 413
20.10.2 RapidIO 413
20.10.3 光纤通道 413
20.10.4 iSCSI 413
第21章 调试设备驱动程序 414
21.1 kdb 414
21.1.1 进入调试器 415
21.1.2 kdb 415
21.1.3 kgdb 417
21.1.4 gdb 420
21.1.5 JTAG调试器 421
21.1.6 下载 423
21.2 内核探测器 423
21.2.1 kprobe 423
21.2.2 jprobe 427
21.2.3 返回探针 429
21.2.4 局限性 431
21.2.5 查看源代码 431
21.3 kexec与kdump 431
21.3.1 kexec 432
21.3.2 kdump与kexec协同工作 432
21.3.3 kdump 433
21.3.4 查看源代码 437
21.4 性能剖析 437
21.4.1 利用OProfile剖析内核性能 438
21.4.2 利用gprof剖析应用程序性能 440
21.5 跟踪 441
21.6 LTP 444
21.7 UML 444
21.8 诊断工具 444
21.9 内核修改配置选项 444
21.10 测试设备 445
第22章 维护与发布 446
22.1 代码风格 446
22.2 修改标记 446
22.3 版本控制 447
22.4 一致性检查 447
22.5 构建脚本 448
22.6 可移植代码 450
第23章 结束语 451
23.1 流程一览表 451
23.2 下一步该做什么 452
附录A Linux汇编 453
附录B Linux与BIOS 457
附录C seq文件 461
前言
20世纪90年代末,我们IBM的一群同事将Linux内核移植到了一种智能手表上。目标设备虽然微不足道,但是移植Linux的任务却相当艰巨。在当 时,内核中还不存在MTD(Memory Technology Device,内存技术设备)子系统,这意味着为了让文件系统能够运行在这种手表的闪存中,我们不得不从头开发必要的存储驱动程序。由于当时内核的输入事 件驱动程序接口尚未诞生,因此手表的触摸屏与用户应用程序的接口非常复杂。让X Windows运行在手表的LCD上十分困难,因为X Windows和帧缓冲设备驱动程序搭配得并不好。如果你戴着一块防水的Linux智能手表,却不能躺在浴缸里实时获得股票行情,那么这块手表还有什么用 呢?Linux几年前就已集成了蓝牙技术,而当时我们却花费了数月的时间将一种专有的蓝牙协议栈移植到手表上,从而使得这种手表可以联上因特网。电源管理 系统虽然只能从手表的电池中多“榨出”短短几个小时时间,但也算够意思了;实际上,为了解决这个棘手的问题,我们也没少花心思。那时候,Linux红外项 目Linux-Infrared还不稳定,而为了使用红外键盘输入数据,我们不得不与其协议栈小心翼翼地周旋。最后,由于当时还没有能应用于消费类电子产 品的成型的编译器发行版,我们也只能自己编个编译器,并交叉编译出一个紧凑的应用程序集。
时光飞逝,当年的小企鹅已经成长为一名健壮的少年。过去我们编写了成千上万行代码并耗时一年完成的任务,若采用现在的内核,只需要几天就可以完成。但是,要成为一名能巧妙地解决多种问题的高级内核工程师,就必须理解今天的Linux内核提供的各种功能和设施。
关于本书
在Linux内核源代码树提供的各个子系统中,drivers/目录是其中最大的一个分支,它比其他子系统大数倍。随着各种新技术的广泛应用,内核中新的设备驱动程序的开发工作正在稳步加速。最新的Linux内核支持多达70余种设备驱动程序。
本书主要讲解如何编写Linux设备驱动程序,介绍了目前内核所支持的主要设备类型的设计与开发,其中包括当年我在将Linux移植到手表中时未遇到的设 备。本书在讲解每类设备驱动程序的时候,都会先介绍与该驱动程序相关的技术,接着给出一个实际的开发例子,最后列出相关的内核源代码文件。在介绍 Linux设备驱动程序之前,本书先介绍了内核以及Linux 2.6的重要特性,重点介绍了设备驱动程序编写者感兴趣的内核知识。
读者对象
本书面向渴望在Linux内核上开发新设备驱动程序的中级程序员。要阅读本书,读者需要具备与操作系统相关的基本概念。比如,要知道什么是系统调用,理解 为什么在内核开发中需要关注并发问题。本书假定读者已经下载了Linux,浏览过Linux内核源代码,并至少浏览过一些相关的文档。另外,读者必须能非 常熟练地使用C语言。
各章概述
前4章为阅读本书其他部分打下了基础,接下来的16章讨论了不同类型的Linux设备驱动程序,之后的第21章描述了设备驱动程序的调试技术,第22章讲 解了维护和交付设备驱动程序的相关事宜,最后一章给出了当接到一个新设备驱动程序开发任务的时候,要首先查验的项目清单。
第1章是引言,简单介绍了Linux系统,讲解了下载内核源代码、进行小的代码修改以及建立可启动的Linux内核映像。
第2章引导读者轻松地进入Linux内核的内部结构,讲解了一些必要的内核概念。首先讲述了内核的启动进程,接下来描述了与驱动程序开发相关的内核API,譬如内核定时器、并发管理以及内存分配等。
第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设备驱动程序。
时光飞逝,当年的小企鹅已经成长为一名健壮的少年。过去我们编写了成千上万行代码并耗时一年完成的任务,若采用现在的内核,只需要几天就可以完成。但是,要成为一名能巧妙地解决多种问题的高级内核工程师,就必须理解今天的Linux内核提供的各种功能和设施。
关于本书
在Linux内核源代码树提供的各个子系统中,drivers/目录是其中最大的一个分支,它比其他子系统大数倍。随着各种新技术的广泛应用,内核中新的设备驱动程序的开发工作正在稳步加速。最新的Linux内核支持多达70余种设备驱动程序。
本书主要讲解如何编写Linux设备驱动程序,介绍了目前内核所支持的主要设备类型的设计与开发,其中包括当年我在将Linux移植到手表中时未遇到的设 备。本书在讲解每类设备驱动程序的时候,都会先介绍与该驱动程序相关的技术,接着给出一个实际的开发例子,最后列出相关的内核源代码文件。在介绍 Linux设备驱动程序之前,本书先介绍了内核以及Linux 2.6的重要特性,重点介绍了设备驱动程序编写者感兴趣的内核知识。
读者对象
本书面向渴望在Linux内核上开发新设备驱动程序的中级程序员。要阅读本书,读者需要具备与操作系统相关的基本概念。比如,要知道什么是系统调用,理解 为什么在内核开发中需要关注并发问题。本书假定读者已经下载了Linux,浏览过Linux内核源代码,并至少浏览过一些相关的文档。另外,读者必须能非 常熟练地使用C语言。
各章概述
前4章为阅读本书其他部分打下了基础,接下来的16章讨论了不同类型的Linux设备驱动程序,之后的第21章描述了设备驱动程序的调试技术,第22章讲 解了维护和交付设备驱动程序的相关事宜,最后一章给出了当接到一个新设备驱动程序开发任务的时候,要首先查验的项目清单。
第1章是引言,简单介绍了Linux系统,讲解了下载内核源代码、进行小的代码修改以及建立可启动的Linux内核映像。
第2章引导读者轻松地进入Linux内核的内部结构,讲解了一些必要的内核概念。首先讲述了内核的启动进程,接下来描述了与驱动程序开发相关的内核API,譬如内核定时器、并发管理以及内存分配等。
第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章讲解了如何让闪存在嵌入式设备上运行起来,这一章最后讲解了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文件,它是用于监控和追踪数据点的辅助接口。
本书大体上根据设备和总线的复杂度进行组织,同时也结合了章与章之间互相关联的客观情况。我们从讲解基本的设备类型开始(如字符设备、串口和输入设备), 紧接着介绍简单的串行总线(如I2C和SMBus),之后介绍PCMCIA、PCI和USB等外部I/O总线。由于视频、音频、块和网络设备通常通过这些 I/O总线与处理器连接,因此在介绍完这些总线之后,还讲解了这些设备的驱动程序。之后面向嵌入式Linux,讲述了无线连网和闪存等技术。最后讨论了用 户空间的设备驱动程序。
内核版本
本书总体上紧跟2.6.23/2.6.24内核版本,书中列出的大部分代码都在2.6.23上测试过。如果读者使用的是更新的版本,请通过类似lwn.net的Linux网站了解内核自2.6.23/2.6.24后进行了哪些更改。
本书网站
我特意建立了elinuxdd.com网站,提供与本书相关的更新和勘误等信息。
本书约定
源代码、函数名和shell命令使用代码体。shell提示符为bash]。新名词使用楷体表示。
为了实现代码示例,一些章节修改了原始的内核源代码。为标识出这些修改,新添加的代码前添加了+,删除的代码前则添加了。
为简单起见,本书有时使用了通用的路径名。因此,当遇到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
第13章描述了Linux音频子系统的架构,并给出了音频设备驱动程序的实现方法。
第14章集中描述存储设备(如硬盘)的驱动程序,并介绍Linux块子系统所支持的几种不同的I/O调度策略。
第15章分析了网络设备驱动程序,介绍内核中与网络相关的数据结构以及网络设备驱动程序与协议层接口的实现方法。
第16章描述了各种无线网络设备的驱动程序,如蓝牙、红外、无线局域网WiFi和蜂窝通信等。
第17章讲解了如何让闪存在嵌入式设备上运行起来,这一章最后讲解了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文件,它是用于监控和追踪数据点的辅助接口。
本书大体上根据设备和总线的复杂度进行组织,同时也结合了章与章之间互相关联的客观情况。我们从讲解基本的设备类型开始(如字符设备、串口和输入设备), 紧接着介绍简单的串行总线(如I2C和SMBus),之后介绍PCMCIA、PCI和USB等外部I/O总线。由于视频、音频、块和网络设备通常通过这些 I/O总线与处理器连接,因此在介绍完这些总线之后,还讲解了这些设备的驱动程序。之后面向嵌入式Linux,讲述了无线连网和闪存等技术。最后讨论了用 户空间的设备驱动程序。
内核版本
本书总体上紧跟2.6.23/2.6.24内核版本,书中列出的大部分代码都在2.6.23上测试过。如果读者使用的是更新的版本,请通过类似lwn.net的Linux网站了解内核自2.6.23/2.6.24后进行了哪些更改。
本书网站
我特意建立了elinuxdd.com网站,提供与本书相关的更新和勘误等信息。
本书约定
源代码、函数名和shell命令使用代码体。shell提示符为bash]。新名词使用楷体表示。
为了实现代码示例,一些章节修改了原始的内核源代码。为标识出这些修改,新添加的代码前添加了+,删除的代码前则添加了。
为简单起见,本书有时使用了通用的路径名。因此,当遇到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
序言
拿到这本书,你也许会问:为什么还要写一本Linux设备驱动程序的书呢?这样的书不是已经有一堆了吗?
答案是:相对于其他同类书,本书实现了一个巨大的突破。
首先,本书与时俱进,基于最新的2.6内核进行讲解。其次,也是更重要的,本书对驱动程序的讲解非常透彻。大多数设备驱动程序的图书仅仅讲解与标准 Unix内核或操作系统相关的主题,譬如串口、磁盘驱动和文件系统等,如果你运气好,可能也会碰到讲解网络协议栈的内容。
本书前进了一大步,它没有避重就轻,而是知难而上,探讨了在现代PC和嵌入式系统中必须面对的难点,比如PCMCIA、USB、I2C、视频、音频、闪存、无线通信等。你可以这样定位本书:Linux内核包含了什么,本书就会告诉你什么。
它毫无遗漏,应有尽有。
何况,作者早就取得了不凡的成就:仅仅是看到他在20世纪90年代末将Linux移植到了手表中的相关介绍就让人激动不已。
本书能成为Prentice Hall开源软件开发系列丛书中的一本,我感到非常激动和欣慰。开源领域从来不乏振奋人心的事件,但本书的面世无疑更加引人瞩目。我希望你能从本书中找到你在进行内核开发时需要的东西,并且也能享受这一过程。
Arnold Robbins
资深Linux技术专家,gawk维护者,Prentice Hall开源软件开发系列丛书编者
答案是:相对于其他同类书,本书实现了一个巨大的突破。
首先,本书与时俱进,基于最新的2.6内核进行讲解。其次,也是更重要的,本书对驱动程序的讲解非常透彻。大多数设备驱动程序的图书仅仅讲解与标准 Unix内核或操作系统相关的主题,譬如串口、磁盘驱动和文件系统等,如果你运气好,可能也会碰到讲解网络协议栈的内容。
本书前进了一大步,它没有避重就轻,而是知难而上,探讨了在现代PC和嵌入式系统中必须面对的难点,比如PCMCIA、USB、I2C、视频、音频、闪存、无线通信等。你可以这样定位本书:Linux内核包含了什么,本书就会告诉你什么。
它毫无遗漏,应有尽有。
何况,作者早就取得了不凡的成就:仅仅是看到他在20世纪90年代末将Linux移植到了手表中的相关介绍就让人激动不已。
本书能成为Prentice Hall开源软件开发系列丛书中的一本,我感到非常激动和欣慰。开源领域从来不乏振奋人心的事件,但本书的面世无疑更加引人瞩目。我希望你能从本书中找到你在进行内核开发时需要的东西,并且也能享受这一过程。
Arnold Robbins
资深Linux技术专家,gawk维护者,Prentice Hall开源软件开发系列丛书编者
媒体评论
“这是我读过的最全面的Linux设备驱动程序著作。”——Theodore Ts’o,Linux基金会首席平台战略师,北美第一位内核开发者
“我要找的就是这样一本书,它告诉我的不只是实例,更重要的是设备驱动程序的设计思路。”
—— Anthony Lawrence,知名操作系统咨询师