笔记:字符设备文件的OPEN/CLOSE操作

应用程序的open函数是如何调用到驱动文件中file_operations结构体中的open函数。

用户空间open函数的原型:

       int open(const char *filename,int flags,mode_t mode);

filename:表示要打开的文件名(/dev/demodev);

flags:指定文件的打开或者创建模式

mode:表示文件的访问权限

返回值:fd文件描述符

fd是一个int型变量,会被用户程序中的read,write,ioctl等函数使用。而在驱动中的read,write,ioctl等函数的第一个参数都是stuct file *filp。显然open函数在申请fd的时候为fd与filp建立了某种联系

内核空间的open函数原型:

       int (*open)(struct inode *,struct file *)

用户空间的程序调用open函数,将发起一个系统调用sys_open

       sys_open①

                            -->do_sys_open-->get_unused_fd_flags②

                                           -->do_filp_open③-->get_empty_filp④

                                                        -->nameidata_to_filp

                                                                      -->__dentry_open⑤

············                                                                                   -->chrdev_open⑥

①:系统调用

②:为本次open操作分配一个未使用过的文件描述符fd

③:首先查找“/dev/demodev”设备文件所对应的inode然后调用get_empty_filp

④:为每一个打开的文件分配一个新的struct file类型的内存空间,即使是打开同一个文件,内核也会生成一个新的struct file对象用来表示当前操作文件的相关信息。struct file中有几个跟设备驱动程序关系密切的成员:struct file_operations * f_op;f_flags用于记录当前文件被打开时所指定的打开模式,这一成员将会影响后续的read/write等函数的行为模式。f_count是对struct file对象的使用计数,当应用程序close一个文件时,只有f_count为0时,才会执行真正的关闭操作。private_data常用来记录设备驱动程序自身定义的数据,可以在file_operations对象其他成员函数之间传递。通过curret可以获得当前的struct tast_struct,task_struct中有个struct files_struct类型的files用来记录打开的文件信息,struct files_struct中有一个struct fdtable类型的fdt成员,struct fdtable类型中有一个stuct file类型的fd,代表一个sruct file类型的数组,通过 current->files->fdtable->fd[fd] = filp.其中filp为新创建出来的struct file类型对象,这样,后续的read,write等函数就可以通过fd找到对应的filp

⑤:将“/dev/demodev”对应的inode中的i_fop赋值给filp->f_op,而i_fop= def_chr_fops,def_chr_fops->open = chrdev_open。

⑥:该函数首先通过inode->i_rdev来查找设备号所对应的设备(设备驱动中的cdev),然后将该cdev->ops 赋值给filp->f_op。(cdev_init将字符驱动中的file_operations赋值给了cdev->ops),至此,filp->f_op指向了字符驱动中的struct file_operations,,接下来就会调用字符设备驱动中的open函数

字符设备的close操作

针对close的系统调用为sys_close,在sys_close中,首先通过文件描述符fd获得对应的file,然后调用filp_close函数,filp_close中首先会判断filp->f_count是否为0,如果为0,说明已经被关闭了直接返回0。如果不为0,会判断filp->count是否为1,为1的话说明就可以关闭了

图中,当应用程序打开一个设备文件时,将通过系统调用sys_open 进入内核空间。在内核

空间将主要由do_sys_open 函数负责发起整个设备文件打开操作,它首先要获得该设备文

件所对应的inode,然后调用其中的i_fop 函数,对字符设备节点的inode 而言, i_fop 函数就是chrdev_ open ( 圈中标号1 的线段),后者通过inode 中的i_rdev 成员在cdev_map 中查找该设备文件所对应的设备对象cdev ( 图中标号2 的线段),在成功找到了该设备对象之后,将inode 的i_cdev 成员指向该字符设备对象(图中标号3 的线段〉,这样下次再对该设备文件节点进行打开操作时,就可以直接通过i_cdev 成员得到设备节点所对应的字符设备对象,而无须再通过cdev_map 进行查找。内核在每次打开一个设备文件时,都会产生一个整型的文件描述符fd 和一个新的struct file 对象filp 来跟踪对该文件的这一次操作,在打开设备文件时,内核会将filp 和fd关联起来,同时会将cdev 中的ops 赋值给filp->f_op (图中标号4 的线段)。最后,sys_open 系统调用将设备文件描述符fd返回到用户空间,如此在用户空间对后续的文件操作read 、write 和ioctl 等函数的调用,将会通过该fd 获得文件所对应的flip,根据filp中的f_op 就可以调用到该文件所对应的设备驱动上实现的函数。

                                                                 ------参考《深入Linux设备驱动程序内核机制》

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值