字符设备文件的打开

打开字符设备文件,还是通过 sys_open() 系统调用。在经过一连串的调用后,内核会走到 __dentry_open() 函数。在这个函数中,执行了以下代码片段:

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);
        p = inode->i_cdev;
        if (!p) {
            inode->i_cdev = p = new;
            inode->i_cindex = idx;
            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;
    filp->f_op = fops_get(p->ops);
    if (!filp->f_op) {
        cdev_put(p);
        return -ENXIO;
    }
    if (filp->f_op->open) {
        lock_kernel();
        ret = filp->f_op->open(inode,filp);
        unlock_kernel();
    }
    if (ret)
        cdev_put(p);
    return ret;
}


简单地说,这个函数从字符设备文件的 inode 节点中取出 cdev 结构的指针(如果 inode 是第一次打开的话,则通过 kobj_lookup() 根据设备号从 cdev_map 中找出 cdev,并保存在 inode->i_cdev 中)。然后用  cdev->ops 替换 file->f_op 从而使用字符设备驱动自己提供的 file_operations。最后,调用字符设备驱动提供的 open 方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值