news 2026/5/15 22:23:42

Linux file->private

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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_deviceplatform_driver的生命周期由内部的devicedriver管理,通过container_of实现双向访问

四、实际是"资源"与"实体"的区别

  • evm_ 只适用于 probe 期间获取的"资源": ✅ 内存(kmalloc) ✅ IO 映射(ioremap) ✅ 中断(request_irq) ✅ GPIO(gpio_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.32(2009年)才正式引入

六、linux驱动开发中如果一个驱动出现内存问题其它驱动都有影响吗还是说隔离的

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/15 22:22:17

基于3D打印与微控制器的复古街机复刻实战指南

1. 项目概述&#xff1a;为什么选择复刻一台“Computer Space”&#xff1f;如果你对电子游戏的历史稍有了解&#xff0c;就会知道“Computer Space”这个名字的分量。作为商业电子游戏的开山鼻祖之一&#xff0c;它在1971年由Nutting Associates推出&#xff0c;其独特的飞碟造…

作者头像 李华
网站建设 2026/5/15 22:21:38

Taotoken 控制台功能详解与 API 密钥安全最佳实践

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 Taotoken 控制台功能详解与 API 密钥安全最佳实践 作为大模型聚合分发平台&#xff0c;Taotoken 的控制台是用户管理模型调用、控制…

作者头像 李华
网站建设 2026/5/15 22:19:24

WordPecker模板库使用指南:如何快速获取专业策划的词汇列表

WordPecker模板库使用指南&#xff1a;如何快速获取专业策划的词汇列表 【免费下载链接】wordpecker-app A personalized language-learning tool that combines Duolingo-style lessons with your own curated vocabulary lists. Seamlessly add words from books, articles,…

作者头像 李华
网站建设 2026/5/15 22:14:35

嵌入式RTOS核心机制:从任务调度到同步通信的实战解析

1. 从裸机到RTOS&#xff1a;为什么我们需要一个“大脑”来管理任务如果你是从单片机裸机开发转向嵌入式实时操作系统&#xff08;RTOS&#xff09;的&#xff0c;那么第一个冲击性的概念可能就是“任务调度”。在裸机世界里&#xff0c;你的程序通常是一个超级循环&#xff08…

作者头像 李华
网站建设 2026/5/15 22:08:29

Excel实战:日期与时间连接后格式错乱?一招TEXT函数完美解决(附进阶防错指南)

📑 前言 在处理Excel数据时,我们经常会遇到**“日期”和“时间”**被分列存储的情况。为了便于数据导入其他系统或进行数据透视,我们需要将它们合并到同一个单元格中。 很多新手会直接使用 =B2&C2 或者 =B2+C2,结果往往得到一串莫名其妙的数字(如 45623.5625),或者…

作者头像 李华