input_open_file()浅析

来源:互联网 发布:淘宝客服晚上几点下班 编辑:程序博客网 时间:2024/06/05 17:10
/*    当用户空间调用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 0
原创粉丝点击