-
get_unused_fd_flags
先在struct file *fd_array[]
找到一个空闲的元素,为本次操作分配一个未使用过的文件描述符(就是空闲元素的数组下标)。 -
do_file_open
生成一个空白struct file
结构体。
从文件系统中查找到文件对应的inode
。 -
do_dentry_open
/* 把文件对应的inode节点和上一步生成的struct file结构体 */
static int do_dentry_open(struct file *f,
struct inode *inode,
int (*open)(struct inode *, struct file *))
{
...
/* 把inode的i_fop赋值给struct file的f_op。
* 其实就是def_chr_fops中的 open成员函数chrdev_open
*/
f->f_op = fops_get(inode->i_fop);
...
/* 把inode的open赋值给传入的第三个参数 */
if (!open)
open = f->f_op->open;
if (open) {
error = open(inode, f);
if (error)
goto cleanup_all;
}
...
}
- def_chr_fops->chrdev_open(此为默认的 open 操作接口)。
定义在:ebf-buster-linux/fs/char_dev.c
。
static int chrdev_open(struct inode *inode, struct file *filp)
{
const struct file_operations *fops;
struct cdev *p;
struct cdev *new = NULL;
...
struct kobject *kobj;
int idx;
/* 从内核哈希表cdev_map中,根据设备号查找自己注册的sturct cdev,获取cdev中的file_operation接口
* cdev_map:全局变量,保存 cdev,file_operation 的哈希表
* inode->i_rdev:设备号
* 获取到的是所求cdev结构体中的kobj成员
*/
kobj = kobj_lookup(cdev_map, inode->i_rdev,&idx);
/* 由结构体成员地址获取结构体地址 */
new = container_of(kobj, struct cdev, kobj);
...
inode->i_cdev = p = new;
...
/* 获取到自己设计的 fops */
fops = fops_get(p->ops);
...
/* 把cdev中的file_operation接口赋值给struct file的f_op,替换掉原来的
* def_chr_ifops。
* 从此这个文件的fops都是自己实现的fops。
*/
replace_fops(filp, fops);
/* 调用自己实现的file_operation接口中的open函数 */
if (filp->f_op->open) {
ret = filp->f_op->open(inode, filp);
if (ret)
goto out_cdev_put;
}
...
}