字符设备文件的打开
2011-08-22 14:18
197 查看
打开字符设备文件,还是通过 sys_open() 系统调用。在经过一连串的调用后,nameidata_to_filp, 内核会走到 __dentry_open() 函数。在这个函数中,执行了以下代码片段:
其中重要的三行:
其中,f 是 struct file 型的指针,open 是一个函数指针。所以这三行代码主要做了两件事:
1. 给 struct file 型变量的 f_op 字段赋值;
2. 调用 f_op->open() 函数。这里需要说明的是,f_op 字段的值是从 inode->i_fop 中得来的,那 inode->i_fop 的值又是怎么来的呢?对于一个设备文件来说,它的 inode->i_fop 的值是在 mknod() 时由内核根据设备文件的类型默认指定的。对应字符设备文件,i_fop 就指向 def_chr_fops 这个 struct file_operations 型变量。
def_chr_fops 定义在 fs/char_dev.c 文件中:
哈,这个 file_operations 真偷懒,就定义了一个 open 方法。
下面看一下 chrdev_open() 函数的实现,它是所有字符设备文件的最初通用的 open 方法。
简单地说,这个函数从字符设备文件的 inode 节点中取出 cdev 结构的指针(如果 inode 是第一次打开的话,则通过 kobj_lookup() 根据设备号从 cdev_map 中找出 cdev,并保存在 inode->i_cdev 中)。然后用 cdev->ops 替换 file->f_op 从而使用字符设备驱动自己提供的 file_operations。最后,调用字符设备驱动提供的 open 方法。
f->f_mapping = inode->i_mapping; f->f_path.dentry = dentry; f->f_path.mnt = mnt; f->f_pos = 0; f->f_op = fops_get(inode->i_fop); file_move(f, &inode->i_sb->s_files); error = security_dentry_open(f, cred); if (error) goto cleanup_all; if (!open && f->f_op) open = f->f_op->open; if (open) { error = open(inode, f); if (error) goto cleanup_all; } ima_counts_get(f);
其中重要的三行:
f->f_op = fops_get(inode->i_fop); open = f->f_op->open; error = open(inode, f);
其中,f 是 struct file 型的指针,open 是一个函数指针。所以这三行代码主要做了两件事:
1. 给 struct file 型变量的 f_op 字段赋值;
2. 调用 f_op->open() 函数。这里需要说明的是,f_op 字段的值是从 inode->i_fop 中得来的,那 inode->i_fop 的值又是怎么来的呢?对于一个设备文件来说,它的 inode->i_fop 的值是在 mknod() 时由内核根据设备文件的类型默认指定的。对应字符设备文件,i_fop 就指向 def_chr_fops 这个 struct file_operations 型变量。
def_chr_fops 定义在 fs/char_dev.c 文件中:
const struct file_operations def_chr_fops = { .open = chrdev_open, };
哈,这个 file_operations 真偷懒,就定义了一个 open 方法。
下面看一下 chrdev_open() 函数的实现,它是所有字符设备文件的最初通用的 open 方法。
static int chrdev_open(struct inode *inode, struct file *filp) { struct cdev *p; struct cdev *new = NULL; int ret = 0; spin_lock(&cdev_lock); p = inode->i_cdev; if (!p) { struct kobject *kobj; int idx; spin_unlock(&cdev_lock); kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx); if (!kobj) return -ENXIO; new = container_of(kobj, struct cdev, kobj); spin_lock(&cdev_lock); /* Check i_cdev again in case somebody beat us to it while we dropped the lock. */ p = inode->i_cdev; if (!p) { inode->i_cdev = p = new; list_add(&inode->i_devices, &p->list); new = NULL; } else if (!cdev_get(p)) ret = -ENXIO; } else if (!cdev_get(p)) ret = -ENXIO; spin_unlock(&cdev_lock); cdev_put(new); if (ret) return ret; ret = -ENXIO; filp->f_op = fops_get(p->ops); if (!filp->f_op) goto out_cdev_put; if (filp->f_op->open) { ret = filp->f_op->open(inode,filp); if (ret) goto out_cdev_put; } return 0; out_cdev_put: cdev_put(p); return ret; }
简单地说,这个函数从字符设备文件的 inode 节点中取出 cdev 结构的指针(如果 inode 是第一次打开的话,则通过 kobj_lookup() 根据设备号从 cdev_map 中找出 cdev,并保存在 inode->i_cdev 中)。然后用 cdev->ops 替换 file->f_op 从而使用字符设备驱动自己提供的 file_operations。最后,调用字符设备驱动提供的 open 方法。
相关文章推荐
- 字符设备文件的打开
- 字符设备文件的打开
- 字符设备文件的打开操作 open()
- linux字符设备文件的打开操作
- linux字符设备文件的打开操作
- 字符设备文件的打开操作 open()
- 字符设备文件的打开
- 【转】从文件到字符设备
- linux 下两类主要的设备文件:字符设备,块设备
- Linux 字符设备驱动开发基础(六)—— VFS 虚拟文件系统解析
- 20 字符设备驱动相关的函数和参数及实现(虚拟文件)
- 高级字符设备驱动-自动创建设备文件笔记
- Linux设备驱动程序学习(6) -高级字符驱动程序操作[(3)设备文件的访问控制]
- 关于Win 10 vmware12 无法打开内核设备“\\.\Global\vmx86”: 系统找不到指定的文件解决方案
- 如何从内核模式设备驱动程序中打开一个文件以及如何读取或写入文件
- Linux 虚拟文件系统(二)Mount、Open;设备文件、挂载和打开文件
- 无法打开内核设备“\\.\Global\vmx86”: 系统找不到指定的文件
- Linux设备驱动程序学习(6)-高级字符驱动程序操作[(3)设备文件的访问控制]
- 为设备服务的文件系统sysfs--sysfs文件的打开操作
- [lsof]lsof查看哪些设备/文件被占用或者打开