Linux驱动中struct file*与struct inode*指针及参数来源技术问询
咱们逐个拆解你的问题,这些都紧扣Linux内核处理文件I/O和驱动交互的核心逻辑:
struct file*指针指向何处? struct file是Linux内核里用来跟踪一个打开文件实例的核心结构体,它全程存在于内核空间中——别搞混,它不是指向磁盘上的物理文件,而是内核在内存里为这个打开的文件维护的“状态账本”。
当用户进程调用open()系统调用打开文件/设备时,内核会为这次打开操作创建一个struct file实例,你的struct file*指针就指向这个内存中的结构体。里面存了超多关键信息:比如当前文件的读写偏移量、打开模式(只读/读写等)、指向驱动file_operations的指针,还有关联的struct inode指针等等,内核靠它来管理每个打开文件的运行时状态。
struct file*和struct inode*类型的指针变量,它们会指向哪里? 分两种情况看:
- 如果只是单纯声明变量(比如
struct file *my_file;)却不初始化,那这就是个野指针——相当于个“无头苍蝇”,指向内存里的随机地址,直接解引用大概率会触发内核Oops(崩溃),绝对不能这么干。 - 要是想让它们指向有效的内核结构,必须通过内核提供的合法接口获取:
- 要拿到有效的
struct file*,可以用filp_open()函数(注意有使用限制,比如中断上下文不能调用),它会模拟打开文件的操作,返回对应的指针,用完记得用filp_close()释放。 - 要获取
struct inode*,可以用iget()或lookup_one_len()这类函数,从文件系统中加载对应的inode节点,但必须遵循内核的内存管理规则,用完要正确释放引用计数。
- 要拿到有效的
总之,绝对不能随便给这些指针瞎赋值,必须走内核提供的正规途径,不然会破坏内核的内存安全。
file_operations结构体定义里的struct file*和struct inode*参数来自何处?我们能否自定义这些参数的变量名?若不能,这些参数是如何与驱动逻辑关联的? 先给个明确结论:变量名完全可以自定义!内核是按参数的位置和类型传递值,根本不管你给参数起什么名字。比如你把驱动open函数的参数从struct inode *inode, struct file *filp改成struct inode *my_inode, struct file *my_file,完全不影响内核调用,只要类型匹配就行。
那这些参数到底从哪来?
当用户进程发起文件相关的系统调用(比如open()、read())时,内核会先完成一系列前置工作:
- 对于
struct inode*:内核会从文件系统中读取对应文件/设备的inode节点(inode是描述文件/设备元数据的结构体,比如设备号、权限、大小等),加载到内核内存后得到这个指针。 - 对于
struct file*:如果是打开操作,内核会新建一个struct file实例;如果是后续的读写操作,内核会从进程的文件描述符表中找到对应的struct file指针。
之后,内核会根据文件关联的file_operations结构体(也就是你驱动里定义的那个),调用对应的驱动函数(比如open、read),并把刚才拿到的两个指针作为参数传进去。
驱动逻辑就是靠这两个指针和内核、硬件关联起来的:比如你可以通过inode里的i_cdev指针拿到对应的字符设备结构,通过file里的private_data字段存储驱动的私有数据(比如设备的状态信息),这样驱动就能知道当前操作的是哪个设备、文件的状态是什么,从而执行对应的硬件操作。
内容的提问来源于stack exchange,提问作者Rahul Raj

