input_open_file()浅析

/*
    当用户空间调用open()的时候,这个函数最终会被调用。
    这个函数主要:
                将打开文件的f_op替换成了input_handler中定义的fops

                如果以后用户层调用read、write、ioctl....系统调用,
                那么input_handler中fops中定义的对应方法会被调用到

    vfs_read:       
    ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
 {
        ....
        if (file->f_op->read){
            ret = file->f_op->read(file, buf, count, pos);
        }
        ....
}
如: evdev中这些方法会被调用到。
        static const struct file_operationsevdev_fops = {
                    .owner      = THIS_MODULE,
                    .read       = evdev_read,
                    .write      = evdev_write,
                    .poll       = evdev_poll,
                    .open       = evdev_open,
                    .release    = evdev_release,
                    .unlocked_ioctl = evdev_ioctl,
            };

    这个函数和v4l2、framebuffer子系统中的open函数有点类似 .
    v4l2、framebuffer的一些函数以前博文中有分析过。这里就简单的列举一下。

    比如 : v4l2:
            当用户层调用open()的时候,v4l2_open()也会被调用
            static int v4l2_open(struct inode *inode, struct file *filp)
            {
                struct video_device *vdev;
                ...
                vdev = video_devdata(filp);  也是从一个数组中取出对应的video_device
                if (vdev->fops->open) {
                        ret = vdev->fops->open(filp); //也是调用具体设备提供的操作方法
                }
            }   
            不一样的是,在open函数中没有替换file->f_op,它使用的是另外一种策略

            在看fb
            fb_open(struct inode *inode, struct file *file)
            {
                int fbidx = iminor(inode);
                struct fb_info *info;
                int res = 0;

                info = get_fb_info(fbidx);  //也是从一个数组中获取对应的fb_info
                file->private_data = info;
                //也是调用了具体设备提供的操作函数
                if (info->fbops->fb_open) {
                        res = info->fbops->fb_open(info,1);
                }
            }

*/
static int input_open_file(struct inode * inode,struct file *file)
{
    struct input_handler * handler;
    const struct file_operations *old_fops,*new_fops = NULL;
    int err;

    /**
        获取互斥锁----访问临界区----释放互斥锁
    */
    //获取互斥锁,可以被信号打断,在等待锁的过程中
    //如果有信号的到来,该函数返回-EINTR  
    err = mutex_lock_interruptible(&input_mutex);
    if (err)
    {
        return err;
    }
    /**
        minor(ionde) :获取次设备号
        从input_table[]中获取对应的input_handler
        好,看看input_table[]
            一指针数组
            static struct input_handler *input_table[8];
        在什么时候被填充?
            在时间处理层 向核心层 注册input_handler的时候
        int input_register_handler(struct input_handler *handler)
        {
            //如果这个被注册的input_handler提供了file_operations   
            if (handler->fops != NULL) {
                    if (input_table[handler->minor >> 5]) 
                    {
                        retval = -EBUSY;
                        goto out;
                    }
                    //将这个被注册的input_handler依据次设备号位索引值放入到input_table[]中
                    //这个minor = input_table[]中空缺项的索引值
                    input_table[handler->minor >> 5] = handler;
            }   
        }   

        在void input_unregister_handler(struct input_handler *handler)
         {
            ....
            //从input_table[]中删除
            if (handler->fops != NULL){
                input_table[handler->minor >> 5] = NULL;
            }
         }
    */
    handler = input_table[minor(inode)>>5];
    if (handler)
    {
        /**
            将取出来的input_handler的fops赋值给new_fops
            例如:evdev
            input_handler:

                static struct input_handler evdev_handler = {
                    .event      = evdev_event,
                    .connect    = evdev_connect,
                    .disconnect = evdev_disconnect,
                    .fops       = &evdev_fops,  
                    .minor      = EVDEV_MINOR_BASE,
                    .name       = "evdev",
                    .id_table   = evdev_ids,   
                };

            fops:

                static const struct file_operations evdev_fops = {
                    .owner      = THIS_MODULE,
                    .read       = evdev_read,
                    .write      = evdev_write,
                    .poll       = evdev_poll,
                    .open       = evdev_open,
                    .release    = evdev_release,
                    .unlocked_ioctl = evdev_ioctl,
                #ifdef CONFIG_COMPAT
                    .compat_ioctl   = evdev_ioctl_compat,
                #endif
                    .fasync     = evdev_fasync,
                    .flush      = evdev_flush,
                    .llseek     = no_llseek,
                };
        */
        //比如 现在的new_fops 等价于 evdev_fops
        new_fops = fops_get(handler->fops);
    }
    mutex_unlock(&input_mutex);//释放互斥体

    /**
        如果取出来的input_handler中没有定义fops 
        或者定义了fops,但是fops中没有定义open函数,那么会失败返回
    */
    if (!new_fops || !new_fops->open)
    {
        fops_put(new_fops);
        err = -ENODEV;
        goto out;   
    }
    old_fops = file->f_op;

    /**
        将取出来的input_handler的fops赋给 打开文件的f_op
        如果是evdev :这样,以后使用到文件的f_op就变成了 evdev_fops
    */
    file->f_op = new_fops;

    /**
        调用这个input_handler中定义的fops中的open函数
        如果input_handler是evdev的话,evdev_open函数就会被调用
    */
    err = new_fops->open(inode, file);
    if (err) {
        fops_put(file->f_op);
        file->f_op = fops_get(old_fops);
    }
    fops_put(old_fops);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值