1. 程式人生 > >linux裝置:cdev和kobj_map

linux裝置:cdev和kobj_map

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);   /* 找到字元裝置的cdev */
        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);/* ZXG: 這是啥? */
            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); /* 呼叫cdev->ops中的open函式 */
        if (ret)
            goto out_cdev_put;
    }

    return 0;

 out_cdev_put:
    cdev_put(p);
    return ret;
}