Linux 驱动架构全景解析:从设备分类到框架实现深度指南
一、Linux 驱动架构总览
1. Linux 驱动三大核心分类
- 字符设备驱动:基础字符设备、高级子系统、串行通信、工业 I/O。
- 块设备驱动:存储设备、SCSI/SATA/NVMe。
- 网络设备驱动:网络接口、以太网/WiFi。
全面解析了 Linux 驱动架构,涵盖字符、块、网络三大设备类型及其对应框架。详细介绍了 FBdev 与 DRM/KMS 显示框架对比、输入子系统流程、设备树配置及平台设备注册。包含中断处理、DMA 优化、调试工具(printk/ftrace/perf)使用及典型开发实战步骤。旨在帮助开发者建立完整的驱动开发知识体系,掌握从硬件分析到内核部署的全流程技术要点。
| 设备类型 | 驱动框架 | 设备节点示例 | 典型应用 |
|---|---|---|---|
| 显示设备 | FBdev / DRM/KMS | /dev/fb0, /dev/dri/card0 | LCD, OLED, HDMI |
| 输入设备 | Input 子系统 | /dev/input/eventX | 触摸屏,键盘,鼠标 |
| 存储设备 | Block 子系统 | /dev/sda, /dev/mmcblk0 | SSD, U 盘,SD 卡 |
| 网络设备 | NetDevice | eth0, wlan0 | 以太网卡,WiFi |
| 声音设备 | ALSA | /dev/snd/pcm* | 声卡,麦克风 |
| 串行设备 | TTY | /dev/ttyS*, /dev/ttyUSB* | 串口,USB 转串口 |
| 工业传感器 | IIO | /sys/bus/iio/devices | 加速度计,陀螺仪 |
| 通用 IO | GPIO | /sys/class/gpio | LED, 按钮 |
| PWM 设备 | PWM | /sys/class/pwm | 电机控制,背光 |
| USB 设备 | USB Core | /dev/bus/usb/* | USB 外设 |
核心结构:
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 *);
long (*ioctl)(struct file *, unsigned int, unsigned long);
int (*open)(struct inode *, struct file *);
int (*close)(struct inode *, struct file *);
// ...
};
// 注册设备
int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops);
开发流程:
file_operations 操作集I/O 栈结构:
应用层 → 文件系统 → 页缓存 → 块层 → I/O 调度器 → 驱动 → 硬件
核心组件:
struct block_device_operations {
int (*open)(struct block_device *, fmode_t);
void (*release)(struct gendisk *, fmode_t);
int (*ioctl)(struct block_device *, fmode_t, unsigned, unsigned long);
int (*submit_bio)(struct bio *);
// ...
};
struct gendisk {
struct request_queue *queue; // I/O 请求队列
struct block_device_operations *fops;
// ...
};
核心结构:
struct net_device {
char name[IFNAMSIZ]; // 设备名
const struct net_device_ops *netdev_ops; // 操作集
unsigned long features; // 设备特性
int irq; // 中断号
// ...
};
struct net_device_ops {
int (*ndo_open)(struct net_device *dev);
int (*ndo_stop)(struct net_device *dev);
netdev_tx_t (*ndo_start_xmit)(struct sk_buff *skb, struct net_device *dev);
// ...
};
| 特性 | FBdev | DRM/KMS |
|---|---|---|
| 架构年代 | 1993 年 | 2006 年 + |
| 硬件加速 | 无 | 支持 GPU 加速 |
| 多显示器 | 有限支持 | 原生支持 |
| 分辨率切换 | 需重启 X | 动态切换 |
| 3D 渲染 | 不支持 | 完整支持 |
| 内存管理 | 简单线性 | GEM/TTM |
| 合成能力 | 无 | 多图层合成 |
| 垂直同步 | 不支持 | 支持 VSync |
| 适用场景 | 控制台/简单 UI | 现代图形界面 |
| 设备节点 | /dev/fb* | /dev/dri/card* |
事件处理流程:
硬件中断 → 驱动读取数据 → 生成 input_event → 发送到 input 核心 → /dev/input/eventX → 用户空间
核心组件:
// 注册输入设备
struct input_dev *input_allocate_device(void);
void input_set_abs_params(struct input_dev *dev, unsigned int axis, int min, int max, int fuzz, int flat);
int input_register_device(struct input_dev *dev);
// 上报事件
void input_report_key(struct input_dev *dev, unsigned int code, int value);
void input_sync(struct input_dev *dev);
设备树结构:
/gpio-keys {
compatible = "gpio-keys";
button@1 {
label = "Power Button";
gpios = <&gpio1 18 GPIO_ACTIVE_LOW>;
linux,code = <KEY_POWER>;
};
};
&i2c1 {
status = "okay";
touchscreen: gt911@5d {
compatible = "goodix,gt911";
reg = <0x5d>;
interrupt-parent = <&gpio2>;
interrupts = <15 IRQ_TYPE_EDGE_FALLING>;
};
};
驱动解析设备树:
static int probe(struct i2c_client *client) {
struct device_node *np = client->dev.of_node;
int irq = of_irq_get(np, 0);
struct gpio_desc *reset_gpio = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH);
}
平台设备注册:
// 定义平台设备
struct platform_device my_device = {
.name = "my-device",
.id = -1,
.resource = my_resources,
.num_resources = ARRAY_SIZE(my_resources),
};
// 平台驱动
static struct platform_driver my_driver = {
.probe = my_probe,
.remove = my_remove,
.driver = {
.name = "my-device",
.of_match_table = of_match_ptr(my_of_match),
},
};
中断注册流程:
irqreturn_t irq_handler(int irq, void *dev_id) {
// 处理中断
return IRQ_HANDLED;
}
int probe(struct platform_device *pdev) {
int irq = platform_get_irq(pdev, 0);
ret = request_irq(irq, irq_handler, IRQF_TRIGGER_RISING, "my_irq", dev);
}
硬件分析 → 设备树配置 → 驱动框架选择 → 实现核心功能 → 注册设备 → 用户空间接口 → 调试优化 → 电源管理 → 生产部署
1. 硬件分析:
2. 设备树配置:
&i2c1 { my_sensor@48 { compatible = "vendor,sensor"; reg = <0x48>; interrupt-parent = <&gpio2>; interrupts = <5 IRQ_TYPE_EDGE_RISING>; }; };
3. 驱动骨架实现:
static const struct of_device_id sensor_match[] = {
{.compatible = "vendor,sensor"},
{},
};
static struct i2c_driver sensor_driver = {
.probe = sensor_probe,
.remove = sensor_remove,
.driver = {
.name = "my-sensor",
.of_match_table = sensor_match,
},
};
module_i2c_driver(sensor_driver);
4. 核心功能实现:
static int sensor_probe(struct i2c_client *client) {
// 初始化硬件
i2c_write_reg(client, CONFIG_REG, 0x01);
// 注册字符设备
alloc_chrdev_region(&dev_num, 0, 1, "sensor");
cdev_init(&sensor_cdev, &sensor_fops);
cdev_add(&sensor_cdev, dev_num, 1);
// 配置中断
request_irq(client->irq, sensor_irq, IRQF_TRIGGER_RISING, "sensor_irq", NULL);
}
| 工具 | 功能 | 使用示例 |
|---|---|---|
| printk | 内核日志 | printk(KERN_INFO "Value: %d\n", val); |
| ftrace | 函数跟踪 | echo function > /sys/kernel/debug/tracing/current_tracer |
| gdb | 内核调试 | gdb vmlinux /proc/kcore |
| devm | 自动释放 | devm_kzalloc(dev, size, GFP_KERNEL) |
| Valgrind | 内存检测 | valgrind --tool=memcheck |
| perf | 性能分析 | perf record -g -a |
DMA 传输优化:
// 分配 DMA 缓冲区
dma_addr_t dma_handle;
void *buf = dma_alloc_coherent(dev, size, &dma_handle, GFP_KERNEL);
// 启动 DMA 传输
struct dma_async_tx_descriptor *tx;
tx = dmaengine_prep_slave_single(chan, dma_handle, size, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
零拷贝技术:
// 用户空间映射
remap_pfn_range(vma, vma->vm_start, virt_to_phys(buf) >> PAGE_SHIFT, size, vma->vm_page_prot);
应用层 ↓ 系统调用接口 (VFS) ↓ ---------------------------------
| 字符设备 | 块设备 | 网络设备 |
|------------|------------|-----------|
| 输入子系统 | Block 层 | NetDevice |
| 显示框架 | I/O 调度器 | 协议栈 |
| 声音子系统 | 驱动接口 ||
| ... | ... ||
---------------------------------
↓ 硬件抽象层 (HAL) ↓ 物理硬件
驱动开发黄金法则: 理解硬件 → 选择框架 → 设备树配置 → 实现核心 → 严格测试 遵循这个流程,您将能驾驭从简单传感器到复杂显示设备的全类型驱动开发!

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML 转 Markdown 互为补充。 在线工具,Markdown 转 HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML 转 Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online