学习linux基础入门教程,Linux把设备纳入文件系统的范畴来管理。每个设备在Linux系统上看起来都像一个文件,它们存放在/dev目录中,称为"设备节点"或“设备文件”。
每当用户程序要访问某个设备时,通过系统调用,内核根据设备结点的信息调用相应的驱动程序。当驱动程序执行完后,又返回至用户进程。
应用层与驱动层层次结构框图
每一个字符设备都有自己的底层操作函数;也就是说每一个设备都对应着自己的file_operations结构体;
那么打开的文件file->f_op指针应该指向那一个file_operations结构体呢?或者说 file->f_op怎样找到对应的file_operations呢?
这跟打开的设备文件里面的信息有关。
通过分析字符设备的代码来了解其核心过程
-字符设备的源码在文件 fs/char_dev.c中,包括设备号申请函数,cdev注册函数都在这个文件里面实现。
申请设备号的过程分析
-设备号的注册或自动分配函数是下面两个
alloc_chrdev_region()
register_chrdev_region()
-两个函数都会调用__register_chrdev_region()函数;这个函数完成如下操作:
如果是自动分配设备号
在全局数组chrdevs[ ]中找到一个空位,这个空位的数组下标就是主设备号;设置这个空位。
如果是直接注册设备号
以主设备号为下标,找到数组chrdevs[ ]中的成员,设置这个成员;
-全局数组chrdevs[]当前的成员数为255,下标从0-254,也就是说,当前内核的字符设备主设备号范围 0-254.
注册cdev分析
-cdev结构的注册分两步,步是初始化cdev结构;第二步是注册。cdev_add()函数分析如下:
内核使用一个数据结构cdev_map来记录系统中所有的字符设备(cdev);
而设备号的维护是由全局chrdevs[]来完成的;
在驱动模块入口函数中:
-申请设备号:就是在数组chrdevs[]中找一个空位;
-注册字符设备:就是将cdev添加到cdev_map中;
字符设备注册过程如下图:
linux基础入门教程:open系统调用分析
-open系统调用的实现在fs/open.c文件中
do_filp_open()函数经过重重调用,会调用vfs_select_inode 和do_dentry_open
do_filp_open()
path_openat
do_last
vfs_open
inode = vfs_select_inode //获取文件的inode信息
do_dentry_open
//将inode->i_fop拷贝给f->f_op
f->f_op = fops_get(inode->i_fop);
//调用inode->i_fop->open
open = f->f_op->open;
open(inode, f);
inode对应一个文件;我们在创建一个设备文件时,就是创建一个inode;
在用户空间创建设备文件时,对应的inode->i_fop指向fs/char_dev.c中的def_chr_fops,def_chr_fops的成员open指向chrdev_open()函数。
open系统调用的层次如下
chrdev_open函数分析
open系统调用的总体过程如下图:
从上面分析字符设备的框架我们可以得出以下结论:
编写字符设备驱动程序的流程如下:
编写底层操作函数
在全局数据结构chr_devs中找到一个空位;(申请设备号)
将底层操作函数的集合填到cdev_map结构中;(注册cdev)
以上就是粤嵌linux基础入门教程之字符设备驱动框架分析,欢迎大家来粤嵌一起学习交流。