跳至内容
深圳市捷比信实业有限公司 · 产品选型与采购咨询联系业务人员
合金电阻捷比信 · 专业器件主题站

从用户模式开放到内核驱动程序实施过程

问题的根源:在教授Linux的基本驱动程序时,我发现让很多学生感到困惑的是他们并没有真正理解从应用程序层到我们自己编写的驱动程序层的调用过程,所以我写了这篇文章。粗略地描述它。首先,我们知道在当前的Linux系统中,我们总共有大约300个系统调用,其中syscall_table.S列出了所有系统调用表。在此文件中,记录了当前平台系统中提供的所有系统调用表,第五项包括:.lONg sys_open / * 5 * / ------------------ -----------检查sys_open()函数,我们可以看到内部完成的工作是:1.检查打开的文件是否是大文件,如果是,则设置大文件标志: O_LARGEFILE2调用do_sys_open()函数。 3.检查2的调用的返回值ret是否有效。 -------------------------------------------------- --------检查do_sys_open()函数所做的工作:调用getname(),getname函数的主要功能是在使用文件名之前将文件名复制到内核数据区,并返回空格内核在正常结束时分配的第一个地址,发生错误时将返回错误代码。获取系统中可用的文件描述符fd。调用do_filp_open()函数。此函数使用数据结构nameidata来描述与文件相关的文件操作。结构名称数据{struct dentry * dentry; //目录数据结构vfsmount * mnt; //虚拟文件挂载点数据struct qstr last; //散列值unsigned int标志; //文件操作标识符int last_type; //输入无符号深度; char * saved_names [MAX_NESteD_LINKS + 1];联合{struct open_intent open;} intent; //特殊数据}; ------------------------- ------------------- --------------结构文件* do_filp_open(const char *文件名,int标志,int模式){int namei_flags,错误; struct nameidata nd; namei_flags =标志; if(((namei_flags + 1 )& amp; O_ACCMODE)namei_flags ++; //如果标志具有O_WRONLY,则添加O_RDONLYerror = open_namei(filename,namei_flags,mode);,& amp; // open_namei函数主要执行诸如打开文件操作的inode部分之类的操作。 if(!error)返回名称idata_to_filp(nd,标志); //将文件的与inod相关的信息转换为文件结构。返回ERR_PTR(错误); //返回错误代码} -------------------------------------- ------ --------------让我们看一下这个更关键的功能:nameidata_to_filp():struct file *(struct nameidata * nd,int flags)821 {822 struct file * filp; 823824 / *从打开的意图中拾取filp * / 825 filp = nd-> intent.open.file; //将相关文件结构的指针分配给filp。 826 / *文件系统是否为我们初始化了文件? * / 827如果(filp-& gt; f_path.dentry == NULL)828 filp = __dentry_open(nd-& gt; mnt,flags,filp,NULL); // ** ***键功能***** // 829 else830 path_release(nd); 831 return filp; 832} ------------------- ------ ---------------------------------关键功能:__dentry_open():静态结构文件* __dentry_open(结构牙科*牙科,struct vfsmount * mnt,int标志,struct文件* f,int(* open)(struct inode *,struct file *)){...... 695 f-& gt; f_pos = 0; 696 f- & gt; f_op = fops_get(inode-& gt; i_fop); //在此处分配值f-& f_op =& amp_def_chr_fops,请注意inode-> i_fop中的分配以上。 (697)第697章(f,& inode-& gt; i_sb-& gt; s_files); 698699 if(!open& amp; amp; f-& gt; f_op)//调用__dentry_open时,open的值为空,因此!open为true。 700 pen = f-> f_op-> open; //这里将open指定为chrdev_open。 701如果(open){702错误= open(inode,f); // chrdev_open在这里被调用,请参阅以下内容。 703 if(error)704 goto cleanup_all; ......} ---------------------------------- ------------------------在函数chrdev_open(/fs/char_dev.v)中:int chrdev_open(struct inode * inode,struct file * filp) {... kobj = kobj_lookup(cdev_map,inode-i_rdev,& amp; idx); //执行kobj_lookup函数并在cdev_map中找到相应的inode-igt_i_rdev设备。 // cdev_map是256个探测结构的数组,用于查找具有相应设备编号的设备。 // inode-> i_rdev是设备编号。 new = container_of(kobj,struct cdev,kobj); //从kobj的位置计算cdev的内存地址,以获得包含相应kobj的cdev。 inode-i_cdev = p = new; //此时,p是我们想要的设备cdev。 filp-> f_op = fops_get(p-& gtops); / /获取cdev操作集。 //从现在开始,读写操作直接通过file-> f_op链接到我们想要的一组设备操作。 ......} -----------------------------至此,系统通过文件->与我们同在。 f_op已连接设备驱动程序中定义的相关操作。我们在w中实现的功能操作