1. 驱动私有数据的设计哲学
在Linux驱动开发中,私有数据(priv)机制是模块化设计的核心体现。这个设计源于面向对象思想在C语言中的实践——虽然内核是用C写的,但通过priv结构体,我们实现了类似"类实例"的概念。每个设备实例都有自己独立的数据存储空间,互不干扰。
我见过不少新手驱动开发者直接使用全局变量来存储设备状态,这是极其危险的做法。当系统中存在多个相同设备时,全局变量会导致状态混乱。而priv机制完美解决了这个问题,它通过将数据与设备实例绑定,确保了数据的隔离性。
2. 私有数据结构体的定义
2.1 典型priv结构体组成
一个完整的priv结构体通常包含以下几类成员:
c复制struct mydrv_private {
struct device *dev; // 关联的设备指针
struct mutex lock; // 设备级互斥锁
struct gpio_desc *reset_gpio; // GPIO控制引脚
struct cdev cdev; // 字符设备结构
void __iomem *regs; // 映射的寄存器地址
int irq_num; // 中断号
struct work_struct work; // 工作队列
u8 config_reg; // 配置寄存器缓存
// 其他设备特定数据...
};
注意:结构体命名通常采用"驱动名_private"的形式,这是内核社区的约定俗成。
2.2 内存对齐考量
在定义priv结构体时,内存对齐是需要特别注意的。不当的对齐会导致内存浪费甚至性能问题。例如:
c复制struct bad_example {
u8 mode; // 1字节
u32 status; // 4字节
u16 count; // 2字节
}; // 由于对齐,实际占用12字节而非7字节
优化后的版本:
c复制struct good_example {
u32 st
