Linux设备驱动程序(第3版)
原名:Linux Device Drivers, 3rd Edition
作者:Jonathan Corbet, Alessandro Rubini, Greg Kroah-Hartman
译者:quickwhale
页数:510页
文件大小:3.15MB
核心概述
本书是Linux设备驱动开发领域的经典教材,系统讲解了Linux内核中设备驱动程序的开发方法。涵盖从基础模块开发到复杂字符驱动、block驱动、网络驱动、PCI驱动、USB驱动的完整知识体系。
目录结构
第一部分:基础概念
第1章 设备驱动简介
- 驱动程序的角色:内核与硬件的桥梁
- 可加载模块机制
- 设备和模块的分类
- 版本编号与版权条款
第2章 建立和运行模块
- HELLO WORLD模块入门
- 用户空间与内核空间的界限
- 内核的并发问题
- 编译、加载和卸载模块
- 内核符号表
- 初始化与错误处理
- 模块参数传递
第二部分:核心驱动开发
第3章 字符驱动
- SCULL(Simple Character Utility for Loading Utilities)设计
- 主次设备编号分配
- 文件操作file_operations结构
- open/release方法
- read/write/v方法实现
第4章 调试技术
- printk函数使用
- /proc文件系统
- oops消息分析
- gdb、kdb、kgdb工具
- 动态探针
第5章 并发和竞争情况
- Linux旗标(semaphore)实现
- 自旋锁API
- 读者/写者锁
- completions机制
- seqlock、RCU等无锁算法
第三部分:高级驱动
第6章 高级字符驱动操作
- ioctl接口设计
- select/poll机制
- mmap内存映射
- proc文件系统深入
第7章 阻塞I/O
- 等待队列使用
- 睡眠与唤醒机制
第8章 中断处理
- 中断顶半部/底半部
- tasklet、workqueue
- softirq机制
第四部分:总线与硬件接口
第9章 并行口驱动
- 早期打印机端口编程
第10章 SCSI架构介绍
- SCSI命令处理流程
第11章 SCSI驱动开发
- host template结构
- 命令处理回调
第12章 USB驱动开发
- USB设备模型
- 驱动绑定机制
- urb提交与完成处理
第13章 PCI设备驱动
- PCI配置空间访问
- 资源分配与管理
第14章 混合驱动
- interruptible_sleep_on安全性问题
- 正确的等待队列用法
第五部分:特殊子系统
第15章 I2C驱动
- I2C总线协议
- 适配器与客户端驱动
第16章 SPI驱动
- 串行外设接口
- 主控制器驱动
第17章 平台驱动
- 设备-驱动匹配机制
- platform_device/platform_driver
第18章 tty驱动
- tty_driver结构
- termios线路设置
- flip缓冲区机制
第19章 驱动模型
- sysfs文件系统
- kobject/kset机制
- uevent事件
第20章 异步I/O
- 文件描述符与进程关联
- SIGIO信号机制
- epoll/poll扩展
第21章 网络驱动
- net_device结构
- 数据包发送与接收
第22章 Framebuffer驱动
- fb_info结构
- 显存映射与操作
第23章 设备树
- DTB格式
- 驱动匹配机制
第24章 设备驱动模型进阶
- 设备电源管理
- 运行时电源管理
第25章 驱动实例化
- 动态设备创建
- 热插拔处理
第26章 安全与驱动
- 驱动权限控制
- 安全模块集成
核心知识点
1. 设备类型
| 类型 | 特点 | 示例 |
|---|---|---|
| 字符设备 | 字节流访问,无缓冲 | 串口、键盘 |
| 块设备 | 块级访问,有缓冲 | 硬盘、SSD |
| 网络设备 | 分组传输 | 网卡 |
2. 设备编号
- 主编号:标识设备驱动类型
- 次编号:标识具体设备实例
- 动态分配:
alloc_chrdev_region() - 静态分配:
register_chrdev_region()
3. 核心数据结构
struct file_operations {
ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
int (*open)(struct inode *, struct file *);
int (*release)(struct inode *, struct file *);
long (*unlocked_ioctl)(struct file *, unsigned int, unsigned long);
int (*mmap)(struct file *, struct vm_area_struct *);
};4. 并发控制机制
- 互斥锁(mutex):睡眠锁,适用于长时间持有
- 自旋锁(spinlock):忙等待,适用于短临界区
- 读写锁:允许多读者或单一 writer
- RCU:读时拷贝更新,适合读多写少场景
- atomic_t:原子操作,适用于简单计数器
5. 中断处理
// 请求中断
request_irq(irq, handler, flags, name, dev);
// 释放中断
free_irq(irq, dev);
// 底半部处理
tasklet_schedule(&t);关键概念
用户空间 vs 内核空间
- 用户空间程序通过系统调用进入内核
- 驱动运行在内核空间,有直接硬件访问权限
- 不允许在内核中执行可能睡眠的操作(除非明确允许)
SCULL模型
本书用SCULL(简单字符加载工具)作为贯穿全书的示例:
- 演示字符驱动的基本框架
- 展示内存分配与管理
- 体现各种并发控制技术的应用
驱动加载流程
- 模块初始化函数注册设备
- 创建设备节点(mknod或udev)
- 用户程序open设备文件
- 调用驱动的read/write/ioctl方法
- 模块卸载时清理资源
重要API速查
| 功能 | 函数 |
|---|---|
| 分配字符设备区域 | alloc_chrdev_region() |
| 注册字符驱动 | cdev_init() + cdev_add() |
| 注销字符驱动 | cdev_del() |
| 分配内存 | kmalloc() / kzalloc() |
| 释放内存 | kfree() |
| 复制数据到用户空间 | copy_to_user() |
| 从用户空间复制 | copy_from_user() |
| 请求中断 | request_irq() |
| 释放中断 | free_irq() |
| 打印消息 | printk() |
| 自旋锁加锁 | spin_lock() / spin_lock_irqsave() |
| 自旋锁解锁 | spin_unlock() / spin_unlock_irqrestore() |
| 互斥锁 | mutex_lock() / mutex_unlock() |
与其他知识的关联
- LINUX内核源代码情景分析-毛德操胡希明 - 内核底层原理
- Linux内核设计与实现-第3版 - 内核架构视角
- 计算机组成/Structured-Computer-Organization-6th-Edition - 硬件基础
- 深入理解计算机系统第2版-CS-APP - 系统层次视图
学习建议
- 循序渐进:从第2章hello world模块开始,理解模块机制
- 动手实践:每章都有示例代码,建议在虚拟机中编译运行
- 关注并发:第5章并发控制是驱动开发的难点和重点
- 理解中断:第8章中断处理是实时性的关键
- 跟踪内核:结合内核源码阅读,理解实际实现
备注
- 本书基于Linux 2.6内核,部分API在4.x/5.x内核中有变化
- 建议结合最新内核源码对照学习
- 中文译本质量良好,术语翻译准确