Linux驱动程序三大结构:inode,file,file(3)

struct file
--882-->f_path里存储的是open传入的路径,VFS就是根据这个路径逐层找到相应的inode
--883-->f_inode里存储的是找到的inode
--884-->f_op里存储的就是驱动提供的file_operations对象,这个对象在open的时候被填充,具体地,应用层的open通过层层搜索会调用inode.i_fops->open,即chrdev_open()
--891-->f_count的作用是记录对文件对象的引用计数,也即当前有多少个使用CLONE_FILES标志克隆的进程在使用该文件。典型的应用是在POSIX线程中。就像在内核中普通的引用计数模块一样,最后一个进程调用put_files_struct()来释放文件描述符。
--892-->f_flags当打开文件时指定的标志,对应系统调用open的int flags,比如驱动程序为了支持非阻塞型操作需要检查这个标志是否有O_NONBLOCK。
--893-->f_mode;对文件的读写模式,对应系统调用open的mod_t mode参数,比如O_RDWR。如果驱动程序需要这个值,可以直接读取这个字段。
--905-->private_data表示file结构的私有数据

我在Linux设备管理(二)_从cdev_add说起一文中已经分析过chrdev_open(),这里仅作概述。

//fs/chr_dev.c 348 /* 349 * Called every time a character special file is opened 350 */ 351 static int chrdev_open(struct inode *inode, struct file *filp) 352 { /* 搜索cdev */ ... 390 replace_fops(filp, fops); 391 if (filp->f_op->open) { 392 ret = filp->f_op->open(inode, filp); 393 if (ret) 394 goto out_cdev_put; 395 } ... 402 }

可以看出,这个函数有三个任务(划重点!!!):

chrdev_open()
--352-389-->利用container_of等根据inode中的成员找到相应的cdev
--390-->用cdev.fops替换filp->f_op,即填充了一个空的struct file的f_op成员。
--392-->回调替换之后的filp->f_op->open,由于替换,这个其实就是cdev.fops

至此,我们知道了我们写的驱动中的open()在何时会被回调,这样我们就可以实现很多有意思的功能,比如,
我们可以在open中通过inode->cdev来识别具体的设备,并将其私有数据隐藏到file结构的private_data中,进而识别同一个驱动操作一类设备;
我们也可以在回调cdev.fops->open()阶段重新填充file结构的fop,进而实现同一个驱动操作不同的设备,这种思想就是内核驱动中常用的分层!
最后总结一下这些结构之间的关系:

Linux驱动程序三大结构:inode,file,file

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/2a01ec7db973b2d233fe8cc3c3ec7dab.html