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(简单字符加载工具)作为贯穿全书的示例:

  • 演示字符驱动的基本框架
  • 展示内存分配与管理
  • 体现各种并发控制技术的应用

驱动加载流程

  1. 模块初始化函数注册设备
  2. 创建设备节点(mknod或udev)
  3. 用户程序open设备文件
  4. 调用驱动的read/write/ioctl方法
  5. 模块卸载时清理资源

重要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()

与其他知识的关联


学习建议

  1. 循序渐进:从第2章hello world模块开始,理解模块机制
  2. 动手实践:每章都有示例代码,建议在虚拟机中编译运行
  3. 关注并发:第5章并发控制是驱动开发的难点和重点
  4. 理解中断:第8章中断处理是实时性的关键
  5. 跟踪内核:结合内核源码阅读,理解实际实现

备注

  • 本书基于Linux 2.6内核,部分API在4.x/5.x内核中有变化
  • 建议结合最新内核源码对照学习
  • 中文译本质量良好,术语翻译准确