Linux file->private

Linux file->private 一、存共享硬件对象static int my_open(struct inode *inode, struct file *file) { struct my_dev *dev container_of(inode-i_cdev, struct my_dev, cdev); file-private_data dev; // 存共享硬件对象省去后续 container_of return 0; } static long my_ioctl(struct file *file, ...) { struct my_dev *dev file-private_data; // 直接使用O(1) 访问 }典型例子RTC 驱动static int rtc_dev_open(struct inode *inode, struct file *file) { struct rtc_device *rtc container_of(inode-i_cdev, struct rtc_device, cdev); file-private_data rtc; // 所有 fd 共享同一个 rtc_device return 0; }读取 RTC 时间硬件只有一个“当前时间”读 10 次都一样不需要记录“我这个 fd 读到了第几个字节”rtc-ops-read_time()是纯函数无副作用二、存本文件私有结构struct my_file_data { int pos; // 本文件的读写位置 int flags; // 本文件的 O_NONBLOCK 等标志 wait_queue_head_t wait; // 本文件的等待队列 struct my_dev *dev; // 再存一份硬件指针可选 }; static int my_open(struct inode *inode, struct file *file) { struct my_dev *dev container_of(inode-i_cdev, struct my_dev, cdev); struct my_file_data *data kmalloc(sizeof(*data), GFP_KERNEL); >代码位置drivers/rtc/class.c rtc_class-dev_groups rtc_groups; // 所有 rtc 设备自动继承 效果 所有 struct rtc_device 都会长出 time、date、wakealarm 等文件 驱动 不写一行代码属性就自动有了 属性是 “通用属性” 与具体芯片无关 适用场景 子系统框架RTC、input、video、sound 属性是所有同类设备共有的如 RTC 都必须能读时间2. 设备层级绑定驱动私有属性代码位置某个具体驱动的probe()里static int my_sensor_probe(struct i2c_client *client, ...) { struct device *dev client-dev; // 创建驱动私有的属性 device_create_file(dev, dev_attr_custom_reg); device_create_file(dev, dev_attr_sampling_rate); return 0; } 效果 只有 这个设备 有 custom_reg 文件 其他同芯片的驱动不会自动继承 属性是 “私有属性” 只有这个驱动需要 适用场景 某个芯片有特殊寄存器如校准值、工作模式 属性只对这个设备有意义3. 驱动层级绑定driver 属性代码位置struct device_driver定义时static struct driver_attribute drv_attr_version __ATTR_RW(version); static struct attribute *sensor_driver_attrs[] { drv_attr_version.attr, NULL }; ATTRIBUTE_GROUPS(sensor_driver); static struct platform_driver sensor_driver { .driver { .name sensor, .groups sensor_driver_groups, // 绑在 driver 上 }, .probe sensor_probe, }; 效果 属性出现在 /sys/bus/platform/drivers/sensor/ 目录下 与 具体设备实例无关没 probe 也能看到 存的是驱动版本号、固件信息等全局信息 适用场景 驱动自身的元信息版本、编译时间、许可证 调试开关影响所有设备实例4、一张图对比三者的作用域/sys/ ├── class/rtc/ ← 类绑定通用属性 │ └── rtc0/ │ ├── time ← 所有 RTC 都有 │ ├── date │ └── wakealarm │ ├── bus/i2c/devices/ ← 设备绑定私有属性 │ └── 1-0050/ │ ├── name │ └── custom_reg ← 只有这个传感器有 │ └── bus/platform/drivers/my-sensor/ ← 驱动绑定驱动级属性 └── version ← 驱动版本信息5. 一句话总结类绑定是“批发”所有设备自动有设备绑定是“零售”单个设备自己加驱动绑定是“品牌标签”驱动自己的信息。RTC 用类绑定因为它是个框架具体芯片驱动用设备绑定加私有寄存器。1. 基本用法#include linux/io.h // 错误做法可能被优化掉 u32 value *reg; // 编译器可能认为没变化直接复用旧值 // 正确做法强制读 u32 value readl(reg); readb(addr) 8 位 (byte) 读 1 字节寄存器 readw(addr) 16 位 (word) 读 2 字节寄存器 readl(addr) 32 位 (long) 读 4 字节寄存器 readq(addr) 64 位 (quad) 读 8 字节寄存器64 位系统 u32 value readl(register_address); 等价于 u32 value *(volatile u32 __iomem *)register_address;#include linux/io.h // readl/writel #include linux/ioport.h // request_mem_region #include linux/of_address.h // of_iomap (设备树) struct my_dev { void __iomem *regs; // 寄存器基地址 }; static int my_probe(...) { // 方式 A设备树获取并映射 dev-regs of_iomap(pdev-dev.of_node, 0); // 方式 B物理地址硬编码 dev-regs ioremap(0x10003000, SZ_4K); // 读寄存器 u32 val readl(dev-regs 0x10); } static int my_remove(...) { iounmap(dev-regs); // 解除映射 }✅您的理解完全正确platform_device最终调用device的注册逻辑platform_driver最终调用driver的注册逻辑✅实现方式通过结构体嵌套不是继承将通用设备模型能力组合到具体设备类型中✅核心价值Linux设备模型提供统一框架各总线子系统只需定义自己的封装结构实现代码复用和统一管理✅生命周期platform_device和platform_driver的生命周期由内部的device和driver管理通过container_of实现双向访问四、实际是资源与实体的区别evm_ 只适用于 probe 期间获取的资源 ✅ 内存kmalloc ✅ IO 映射ioremap ✅ 中断request_irq ✅ GPIOgpio_request ✅ 驱动主动创建的设备如 rtc_device 不适用于实体本身 ❌ 传入的 platform_device外部定义 ❌ platform_driver模块级 ❌ i2c_client由 i2c-core 管理 ❌ spi_device由 spi-core 管理五、Linux 2.4 版本情况确认结论Linux 2.4完全没有devm_函数。引入时间devm_机制在Linux 2.6.322009年才正式引入六、linux驱动开发中如果一个驱动出现内存问题其它驱动都有影响吗还是说隔离的