当前位置: 首页 > news >正文

linux 驱动私有数据

最近在学习字符设备驱动,遇到了一个私有数据的结构
很多教程,例如原子,只是把需要用到的结构体在open时候,把地址传递给filp->private_data
然后再read或write等时候,通过filp->private_data再赋值结构体

原子以及网络上大部分的说法是,避免使用全局变量,实际上全局变量依旧存在,只不过在fops成员函数里面访问时候,不再对全局变量进行直接访问,而通过指针访问。
真正避免全局变量使用应该是在open时候通过kzalloc申请内存,用于存储私有数据,在使用完后进行kfree释放。
这里试图阐述说明私有数据的真实用途。

什么是私有数据?

struct file *filp
在 struct filed有个成员void *private_data
这个字段允许驱动程序在不同的文件操作(如read、write、ioctl等)中访问与特定设备相关的私有信息。

为何要使用私有数据?(私有数据应用目的)

真实目的,为了在同一个驱动支持多个应用程序同时访问时,为各个设备准备的数据结构互相不冲突,避免并发访问问题。
在Linux驱动程序中,通常需要支持多个设备实例。
每个设备都有自己的状态和配置。如果使用全局变量,所有设备将共享这些变量,这在多设备环境下会造成严重问题,因为无法区分不同设备的状态。

私有数据如何实现?

应用程序调用驱动过程

加载一个驱动模块,产生一个设备文件,有唯一对应的inode结构体
应用层调用open函数打开设备文件,对于上层open调用到内核时会发生一次软中断,从用户空间进入到内核空间。
open会调用到sys_open(内核函数),sys_open根据文件的地址,找到设备文件对应的struct inode结构体描述的信息,可以知道接下来要操作的设备类型(字符设备还是块设备),还会分配一个struct file结构体。
根据struct inode结构体里面记录的主设备号和次设备号,在驱动链表(管理所有设备的驱动)里面,根据找到字符设备驱动
每个字符设备都有一个struct cdev结构体。此结构体描述了字符设备所有信息,其中最重要的一项就是字符设备的操作函数接口
找到struct cdev结构体后,linux内核就会将struct cdev结构体所在的内存空间首地址记录在struct inode结构体i_cdev成员中,将struct cdev结构体中的记录的函数操作接口地址记录在struct file结构体的f_ops成员中。
执行xxx_open驱动函数。

long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
{struct open_flags op;int fd = build_open_flags(flags, mode, &op);struct filename *tmp;if (fd)return fd;tmp = getname(filename);if (IS_ERR(tmp))return PTR_ERR(tmp);fd = get_unused_fd_flags(flags);if (fd >= 0) {struct file *f = do_filp_open(dfd, tmp, &op);if (IS_ERR(f)) {put_unused_fd(fd);fd = PTR_ERR(f);} else {fsnotify_open(f);fd_install(fd, f);}}putname(tmp);return fd;
}

do_filp_open这里可以看到,内核为打开的文件创建一个新的’struct file’实例

在这里插入图片描述


struct file {union {struct llist_node	fu_llist;struct rcu_head 	fu_rcuhead;} f_u;struct path		f_path;struct inode		*f_inode;	/* cached value */const struct file_operations	*f_op;/** Protects f_ep_links, f_flags.* Must not be taken from IRQ context.*/spinlock_t		f_lock;atomic_long_t		f_count;unsigned int 		f_flags;fmode_t			f_mode;struct mutex		f_pos_lock;loff_t			f_pos;struct fown_struct	f_owner;const struct cred	*f_cred;struct file_ra_state	f_ra;u64			f_version;
#ifdef CONFIG_SECURITYvoid			*f_security;
#endif/* needed for tty driver, and maybe others */void			*private_data;#ifdef CONFIG_EPOLL/* Used by fs/eventpoll.c to link all the hooks to this file */struct list_head	f_ep_links;struct list_head	f_tfile_llink;
#endif /* #ifdef CONFIG_EPOLL */struct address_space	*f_mapping;
} __attribute__((aligned(4)));	/* lest something weird decides that 2 is OK */struct file_handle {__u32 handle_bytes;int handle_type;/* file identifier */unsigned char f_handle[0];
};

在linux操作系统中,每打开一次文件,Linux操作系统会在VFS层分配一个struct file结构体来描述打开的文件
这里可以看到,每次open都会新建一个实例,这样每个实例都有自己对应的private_data私有函数。这里private_data使用void型,可以指向任何类型的数据结构。
虽然linux使用的c语言,实际上应用了大量面向对象的编程思维。

参考网站:https://blog.csdn.net/ZHUhapi/article/details/138683130

http://www.dtcms.com/a/395710.html

相关文章:

  • 信息系统监理师软考备考指南:组织协调与沟通管理专题精讲
  • 【开题答辩全过程】以 JAVA农产品销售系统为例,包含答辩的问题和答案
  • Python 网络爬虫生态全景综述
  • MCP— Model Context Protocol(模型上下文协议)
  • 解决ubuntu无法连接上security.ubuntu.com:80 (185.125.190.81)的问题
  • SHAP分析 | MATLAB实现XGBoost极限梯度提升树多输入单输出回归预测+SHAP可解释分析分析(预测新数据,多指标评价)
  • 磁共振成像原理(理论)11:梯度回波 (Gradient Echoes)
  • odoo18全局菜单搜索
  • langchain链中的高级组件
  • 鸿蒙:使用animation或animateTo实现图片无限旋转效果
  • 02)阿里 Arthas(阿尔萨斯)开源的 Java 诊断工具原理分析、JVM动态加载“代理程序“(Agent) 的机制、vm.loadAgent原理
  • [学习笔记][机器学习-周志华] 第1章 绪论
  • Node.js面试题及详细答案120题(111-120) -- 进阶与扩展篇
  • 鞋底布线前传:CAD三维建模如何实现精准凸起设计
  • 华为无线网络技术基础
  • Django 模型与 ORM 全解析(二):数据库操作
  • Python 2025:AI与自动化运维的融合新纪元
  • MySQL 核心函数与约束详解
  • 设计模式简要
  • 服务扩容与容量评估手册
  • Pyside6 + QML - 信号与槽08 - 一个函数被多个信号触发(带参数)
  • 【第十一章】Python 调用 MySQL 全面指南:从基础到实践​
  • 新手玩家如何使用云手机
  • 【Datawhale组队学习202509】AI硬件与机器人大模型 task02 视觉感知与手眼协调
  • 基础算法---【前缀和】
  • YOLO系统——yolov1工作原理
  • 第20讲 机器学习中的分类数据
  • 《前端学习总结:GitLab、状态管理、组件库与 Umi.js》
  • 【论文阅读】理解世界还是预测未来?—— 世界模型全面综述
  • AR眼镜:远程协作与精准操作的未来之眼