Linux 设备驱动 中文 Edition 3 第三版 PDF 文档
以 Linux 为代表的自由操作系统的很多优点之一,是它们的内部是开放给所有人看的。操作系统,曾经是一个隐藏的神秘的地方,它的代码只局限于少数的程序员,现在已准备好让任何具备必要技能的人来检查,理解以及修改。
Linux 已经帮助使操作系统民主化,Linux 内核保留有大量的复杂的代码,但是,那些想要成为内核 hacker 的人需要一个入口点,这样他们可以进入代码中,不会被代码的复杂性压倒,通常,设备驱动提供了这样的门路。
目录
第 1 章 设备驱动简介................................... 1
1.1. 驱动程序的角色................................ 1
1.2. 划分内核............................................ 2
1.2.1. 可加载模块................................ 3
1.3. 设备和模块的分类............................ 4
1.4. 安全问题............................................ 6
1.5. 版本编号............................................ 7
1.6. 版权条款............................................ 8
1.7. 加入内核开发社团............................ 9
1.8. 本书的内容........................................ 9
第 2 章 建立和运行模块........................ 11
2.1. 设置你的测试系统.......................... 11
2.2. HELLO WORLD 模块......................... 11
2.3. 内核模块相比于应用程序............... 13
2.3.1. 用户空间和内核空间............... 14
2.3.2. 内核的并发.............................. 15
2.3.3. 当前进程.................................. 15
2.3.4. 几个别的细节.......................... 16
2.4. 编译和加载...................................... 16
2.4.1. 编译模块.................................. 16
2.4.2. 加载和卸载模块...................... 18
2.4.3. 版本依赖.................................. 19
2.4.4. 平台依赖性.............................. 20
2.5. 内核符号表...................................... 21
2.6. 预备知识.......................................... 22
2.7. 初始化和关停.................................. 22
2.7.1. 清理函数.................................. 23
2.7.2. 初始化中的错误处理............... 24
2.7.3. 模块加载竞争.......................... 26
2.8. 模块参数.......................................... 26
2.9. 在用户空间做.................................. 28
2.10. 快速参考........................................ 29
第 3 章 字符驱动.................................... 32
3.1. SCULL 的设计................................... 32
3.2. 主次编号.......................................... 33
3.2.1. 设备编号的内部表示............... 33
3.2.2. 分配和释放设备编号............... 34
3.2.3. 主编号的动态分配.................. 35
3.3. 一些重要数据结构.......................... 37
3.3.1. 文件操作.................................. 37
3.3.2. 文件结构.................................. 41
3.3.3. inode 结构................................ 43
3.4. 字符设备注册.................................. 43
3.4.1. scull 中的设备注册.................. 44
3.4.2. 老方法...................................... 45
3.5. OPEN 和 RELEASE .............................. 45
3.5.1. open 方法................................. 45
3.5.2. release 方法.............................. 47
3.6. SCULL 的内存使用........................... 47
3.7. 读和写.............................................. 50
3.7.1. read 方法.................................. 52
3.7.2. write 方法................................. 53
3.7.3. readv 和 writev ......................... 55
3.8. 使用新设备...................................... 55
3.9. 快速参考.......................................... 56
第 4 章 调试技术.................................... 58
4.1. 内核中的调试支持.......................... 58
4.2. 用打印调试...................................... 60
4.2.1. printk......................................... 60
4.2.2. 重定向控制台消息.................. 62
4.2.3. 消息是如何记录的.................. 62
4.2.4. 打开和关闭消息...................... 63
4.2.5. 速率限制.................................. 65
4.2.6. 打印设备编号.......................... 65
4.3. 用查询来调试.................................. 66
4.3.1. 使用 /proc 文件系统................ 66
4.3.2. ioctl 方法.................................. 73
4.4. 使用观察来调试.............................. 73
4.5. 调试系统故障.................................. 75
4.5.1. oops 消息.................................. 76
4.5.2. 系统挂起.................................. 78
4.6. 调试器和相关工具.......................... 80
4.6.1. 使用 gdb ................................... 80
4.6.2. kdb 内核调试器....................... 83
4.6.3. kgdb 补丁................................. 85
4.6.4. 用户模式 Linux 移植............... 85
4.6.5. Linux 追踪工具........................ 86
4.6.6. 动态探针.................................. 86
第 5 章 并发和竞争情况........................ 87
5.1. SCULL 中的缺陷............................... 87
5.2. 并发和它的管理.............................. 88
5.3. 旗标和互斥体.................................. 89
5.3.1. Linux 旗标实现........................ 89
5.3.2. 在 scull 中使用旗标................. 91
5.3.3. 读者/写者旗标......................... 92
5.4. COMPLETIONS 机制.......................... 93
5.5. 自旋锁.............................................. 95
5.5.1. 自旋锁 API 简介...................... 95
5.5.2. 自旋锁和原子上下文............... 96
5.5.3. 自旋锁函数.............................. 97
5.5.4. 读者/写者自旋锁..................... 98
5.6. 锁陷阱.............................................. 99
5.6.1. 模糊的规则.............................. 99
5.6.2. 加锁顺序规则.......................... 99
5.6.3. 细 -粗- 粒度加锁.................... 100
5.7. 加锁的各种选择............................ 100
5.7.1. 不加锁算法............................ 100
5.7.2. 原子变量................................ 101
5.7.3. 位操作.................................... 103
5.7.4. seqlock 锁............................... 104
5.7.5. 读取-拷贝-更新...................... 105
5.8. 快速参考........................................ 106
第 6 章 高级字符驱动操作.................. 111
6.1. IOCTL 接口...................................... 111
6.1.1. 选择 ioctl 命令....................... 112
6.1.2. 返回值.................................... 115
6.1.3. 预定义的命令........................ 115
6.1.4. 使用 ioctl 参数....................... 116
6.1.5. 兼容性和受限操作................ 118
6.1.6. ioctl 命令的实现.................... 119
6.1.7. 不用 ioctl 的设备控制............ 120
6.2. 阻塞 I/O.......................................... 121
6.2.1. 睡眠的介绍............................ 122
6.2.2. 简单睡眠................................ 122
6.2.3. 阻塞和非阻塞操作................ 124
6.2.4. 一个阻塞 I/O 的例子.............. 125
6.2.5. 高级睡眠................................ 127
6.2.6. 测试 scullpipe 驱动................ 134
6.3. POLL 和 SELECT............................... 135
6.3.1. 与 read 和 write 的交互.......... 137
6.3.2. 底层的数据结构.................... 139
6.4. 异步通知........................................ 140
6.4.1. 驱动的观点............................ 141
6.5. 移位一个设备................................ 142
6.5.1. llseek 实现.............................. 143
6.6. 在一个设备文件上的存取控制..... 144
6.6.1. 单 open 设备.......................... 144
6.6.2. 一次对一个用户限制存取..... 145
6.6.3. 阻塞 open 作为对 EBUSY 的替代.................................................. 146
6.6.4. 在 open 时复制设备............... 148
6.7. 快速参考........................................ 150
第 7 章 时间, 延时, 和延后工作............ 154
7.1. 测量时间流失................................ 154
7.1.1. 使用 jiffies 计数器................. 154
7.1.2. 处理器特定的寄存器............. 156
7.2. 获知当前时间................................ 158
7.3. 延后执行........................................ 159
7.3.1. 长延时.................................... 160
7.3.2. 短延时.................................... 164
7.4. 内核定时器.................................... 165
7.4.1. 定时器 API ............................. 166
7.4.2. 内核定时器的实现................ 169
7.5. TASKLETS 机制............................... 170
7.6. 工作队列........................................ 172
7.6.1. 共享队列................................ 174
7.7. 快速参考........................................ 176
7.7.1. 时间管理................................ 176
7.7.2. 延迟........................................ 177
7.7.3. 内核定时器............................ 178
7.7.4. Tasklets 机制.......................... 178
7.7.5. 工作队列................................ 179
第 8 章 分配内存.................................. 181
8.1. KMALLOC 的真实故事................... 181
8.1.1. flags 参数............................... 181
8.1.2. size 参数................................ 184
8.2. 后备缓存........................................ 184
8.2.1. 一个基于 Slab 缓存的 scull: scullc ................................................ 186
8.2.2. 内存池.................................... 187
8.3. GET_FREE_PAGE 和其友................. 188
8.3.1. 一个使用整页的 scull: scullp . 189
8.3.2. alloc_pages 接口.................... 190
8.3.3. vmalloc 和 其友...................... 191
8.3.4. 一个使用虚拟地址的 scull : scullv ................................................ 193
8.4. 每-CPU 的变量.............................. 194
8.5. 获得大量缓冲................................ 196
8.5.1. 在启动时获得专用的缓冲..... 196
8.6. 快速参考........................................ 197
第 9 章 与硬件通讯.............................. 201
9.1. I/O 端口和 I/O 内存....................... 201
9.1.1. I/O 寄存器和常规内存........... 202
9.2. 使用 I/O 端口................................. 203
9.2.1. I/O 端口分配.......................... 204
9.2.2. 操作 I/O 端口......................... 204
9.2.3. 从用户空间的 I/O 存取.......... 205
9.2.4. 字串操作................................ 206
9.2.5. 暂停 I/O.................................. 206
9.2.6. 平台依赖性............................ 207
9.3. 一个 I/O 端口例子......................... 209
9.3.1. 并口纵览................................ 209
9.3.2. 一个例子驱动........................ 210
9.4. 使用 I/O 内存................................. 211
9.4.1. I/O 内存分配和映射............... 212
9.4.2. 存取 I/O 内存......................... 213
9.4.3. 作为 I/O 内存的端口.............. 214
9.4.4. 重用 short 为 I/O 内存............ 215
9.4.5. 在 1 MB 之下的 ISA 内存....... 215
9.4.6. isa_readb 和其友................... 217
9.5. 快速参考........................................ 217
第 10 章 中断处理................................ 220
10.1. 准备并口...................................... 220
10.2. 安装一个中断处理...................... 220
10.2.1. /proc 接口............................. 223
10.2.2. 自动检测 IRQ 号.................. 224
10.2.3. 快速和慢速处理.................. 228
10.2.4. 实现一个处理...................... 229
10.2.5. 处理者的参数和返回值....... 232
10.2.6. 使能和禁止中断.................. 233
10.3. 前和后半部.................................. 234
10.3.1. Tasklet 实现.......................... 235
10.3.2. 工作队列.............................. 236
10.4. 中断共享...................................... 237
10.4.1. 安装一个共享的处理者....... 237
10.4.2. 运行处理者.......................... 238
10.4.3. /proc 接口和共享中断.......... 239
10.5. 中断驱动 I/O................................ 239
10.5.1. 一个写缓存例子.................. 240
10.6. 快速参考...................................... 243
第 11 章 内核中的数据类型................ 245
11.1. 标准 C 类型的使用...................... 245
11.2. 安排一个明确大小给数据项....... 246
11.3. 接口特定的类型.......................... 247
11.4. 其他移植性问题.......................... 248
11.4.1. 时间间隔.............................. 248
11.4.2. 页大小.................................. 248
11.4.3. 字节序.................................. 248
11.4.4. 数据对齐.............................. 249
11.4.5. 指针和错误值...................... 250
11.5. 链表.............................................. 251
11.6. 快速参考...................................... 255
第 12 章 PCI 驱动................................. 257
12.1. PCI 接口....................................... 257
12.1.1. PCI 寻址............................... 257
12.1.2. 启动时间.............................. 260
12.1.3. 配置寄存器和初始化........... 261
12.1.4. MODULEDEVICETABLE 宏 264
12.1.5. 注册一个 PCI 驱动............... 264
12.1.6. 老式 PCI 探测...................... 266
12.1.7. 使能 PCI 设备...................... 267
12.1.8. 存取配置空间...................... 267
12.1.9. 存取 I/O 和内存空间............ 268
12.1.10. PCI 中断............................. 270
12.1.11. 硬件抽象............................ 270
12.2. 回顾: ISA...................................... 272
12.2.1. 硬件资源.............................. 272
12.2.2. ISA 编程............................... 272
12.2.3. 即插即用规范...................... 273
12.3. PC/104 和 PC/104+ ...................... 273
12.4. 其他的 PC 总线............................ 274
12.4.1. MCA 总线............................. 274
12.4.2. EISA 总线............................. 274
12.4.3. VLB 总线.............................. 274
12.5. SBUS............................................. 275
12.6. NUBUS 总线................................. 275
12.7. 外部总线...................................... 275
12.8. 快速参考...................................... 276
第 13 章 USB 驱动............................... 278
13.1. USB 设备基础知识...................... 279
13.1.1. 端点...................................... 279
13.1.2. 接口...................................... 281
13.1.3. 配置...................................... 282
13.2. USB 和 SYSFS ............................... 282
13.3. USB 的 URBS................................ 284
13.3.1. 结构 struct urb...................... 285
13.3.2. 创建和销毁 urb.................... 291
13.3.3. 提交 urb................................ 294
13.3.4. 完成 urb: 完成回调处理者... 294
13.3.5. 取消 urb................................ 295
13.4. 编写一个 USB 驱动..................... 295
13.4.1. 驱动支持什么设备............... 295
13.4.2. 注册一个 USB 驱动.............. 297
13.4.3. 提交和控制一个 urb............ 303
13.5. 无 URB 的 USB 传送..................... 304
13.5.1. usb_bulk_msg 接口............... 305
13.5.2. usb_control_msg 接口........... 306
13.5.3. 使用 USB 数据函数.............. 307
13.6. 快速参考...................................... 308
第 14 章 LINUX 设备模型..................... 311
14.1. KOBJECTS, KSETS 和 SUBSYSTEMS 312
14.1.1. Kobject 基础......................... 313
14.1.2. kobject 层次, kset, 和子系统. 316
14.2. 低级 SYSFS 操作........................... 319
14.2.1. 缺省属性.............................. 319
14.2.2. 非缺省属性.......................... 321
14.2.3. 二进制属性.......................... 321
14.2.4. 符号连接.............................. 322
14.3. 热插拔事件产生.......................... 322
14.3.1. 热插拔操作.......................... 323
14.4. 总线, 设备, 和驱动...................... 324
14.4.1. 总线...................................... 324
14.4.2. 设备...................................... 327
14.4.3. 设备驱动.............................. 331
14.5. 类.................................................. 333
14.5.1. class_simple 接口................. 334
14.5.2. 完整的类接口...................... 335
14.6. 集成起来...................................... 337
14.6.1. 添加一个设备...................... 338
14.6.2. 去除一个设备...................... 341
14.6.3. 添加一个驱动...................... 341
14.6.4. 去除一个驱动...................... 342
14.7. 热插拔.......................................... 342
14.7.1. 动态设备.............................. 342
14.7.2. /sbin/hotplug 工具................ 343
14.7.3. 使用 /sbin/hotplug ................ 347
14.8. 处理固件...................................... 349
14.8.1. 内核固件接口...................... 350
14.8.2. 它如何工作.......................... 350
14.9. 快速参考...................................... 351
14.9.1. Kobjects结构........................ 351
14.9.2. sysfs 操作.............................. 352
14.9.3. 总线, 设备, 和驱动............... 352
14.9.4. 类.......................................... 353
14.9.5. 固件...................................... 354
第 15 章 内存映射和 DMA.................. 355
15.1. LINUX 中的内存管理................... 355
15.1.1. 地址类型.............................. 355
15.1.2. 物理地址和页...................... 357
15.1.3. 高和低内存.......................... 357
15.1.4. 内存映射和 struct page......... 358
15.1.5. 页表...................................... 360
15.1.6. 虚拟内存区.......................... 360
15.1.7. 进程内存映射...................... 363
15.2. MMAP 设备操作........................... 363
15.2.1. 使用 remap_pfn_range.......... 365
15.2.2. 一个简单的实现.................. 366
15.2.3. 添加 VMA 的操作................ 366
15.2.4. 使用 nopage 映射内存.......... 367
15.2.5. 重新映射特定 I/O 区............ 369
15.2.6. 重新映射 RAM..................... 370
15.2.7. 重映射内核虚拟地址........... 373
15.3. 进行直接 I/O................................ 374
15.3.1. 异步 I/O................................ 376
15.4. 直接内存存取.............................. 379
15.4.1. 一个 DMA 数据传输的概况. 379
15.4.2. 分配 DMA 缓冲.................... 380
15.4.3. 总线地址.............................. 381
15.4.4. 通用 DMA 层........................ 382
15.4.5. ISA 设备的 DMA.................. 390
15.5. 快速参考...................................... 395
15.5.1. 介绍性材料.......................... 395
15.5.2. 实现 mmap ........................... 396
15.5.3. 实现直接 I/O........................ 397
15.5.4. 直接内存存取...................... 397
第 16 章 块驱动.................................... 400
16.1. 注册.............................................. 400
16.1.1. 块驱动注册.......................... 400
16.1.2. 磁盘注册.............................. 401
16.1.3. 在 sbull 中的初始化.............. 403
16.1.4. 注意扇区大小...................... 405
16.2. 块设备操作.................................. 405
16.2.1. open 和 release 方法............. 405
16.2.2. 支持可移出的介质............... 407
16.2.3. ioctl 方法.............................. 407
16.3. 请求处理...................................... 408
16.3.1. 对请求方法的介绍............... 408
16.3.2. 一个简单的请求方法........... 409
16.3.3. 请求队列.............................. 411
16.3.4. 请求的分析.......................... 414
16.3.5. 请求完成函数...................... 419
16.4. 一些其他的细节.......................... 423
16.4.1. 命令预准备.......................... 423
16.4.2. 被标识的命令排队............... 424
16.5. 快速参考...................................... 426
第 17 章 网络驱动................................ 430
17.1. SNULL 是如何设计的................... 430
17.1.1. 分配 IP 号............................ 431
17.1.2. 报文的物理传送.................. 433
17.2. 连接到内核.................................. 433
17.2.1. 设备注册.............................. 433
17.2.2. 初始化每一个设备............... 435
17.2.3. 模块卸载.............................. 436
17.3. NET_DEVICE 结构的详情.............. 437
17.3.1. 全局信息.............................. 437
17.3.2. 硬件信息.............................. 437
17.3.3. 接口信息.............................. 438
17.3.4. 设备方法.............................. 442
17.3.5. 公用成员.............................. 444
17.4. 打开与关闭.................................. 445
17.5. 报文传送...................................... 446
17.5.1. 控制发送并发...................... 448
17.5.2. 传送超时.............................. 448
17.5.3. 发散/汇聚 I/O....................... 449
17.6. 报文接收...................................... 450
17.7. 中断处理...................................... 452
17.8. 接收中断缓解.............................. 454
17.9. 连接状态的改变.......................... 456
17.10. SOCKET 缓存.............................. 457
17.10.1. 重要成员变量.................... 457
17.10.2. 作用于 socket 缓存的函数. 458
17.11. MAC 地址解析.......................... 460
17.11.1. 以太网使用 ARP................ 460
17.11.2. 不考虑 ARP........................ 461
17.11.3. 非以太网头部.................... 461
17.12. 定制 IOCTL 命令......................... 462
17.13. 统计信息.................................... 463
17.14. 多播............................................ 464
17.14.1. 多播的内核支持................ 465
17.14.2. 典型实现............................ 466
17.15. 几个其他细节............................ 467
17.15.1. 独立于媒介的接口支持..... 467
17.15.2. ethtool 支持........................ 468
17.15.3. netpoll ................................. 468
17.16. 快速参考.................................... 468
第 18 章 TTY 驱动............................... 472
18.1. 一个小 TTY 驱动......................... 474
18.1.1. 结构 struct termios ............... 475
18.2. TTY_DRIVER 函数指针................. 478
18.2.1. open 和 close ........................ 478
18.2.2. 数据流.................................. 481
18.2.3. 其他缓冲函数...................... 482
18.2.4. 无 read 函数?....................... 483
18.3. TTY 线路设置............................. 484
18.3.1. set_termios 函数................... 484
18.3.2. tiocmget 和 tiocmset .............. 486
18.4. IOCTLS 函数.................................. 487
18.5. TTY 设备的 PROC 和 SYSFS 处理.. 490
18.6. TTY_DRIVER 结构的细节.............. 491
18.7. TTY_OPERAIONS 结构的细节........ 493
18.8. TTY_STRUCT 结构的细节.............. 495
18.9. 快速参考...................................... 498
下载地址:https://www.wenjiangs.com/wp-content/uploads/2021/10/pIYBAFwnBwOAGVZDAHfaEiLTBrY196.zip
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论