input 子系统的分析与学习(一)
来源:互联网 发布:秦朝灭亡 知乎 编辑:程序博客网 时间:2024/06/05 17:09
依然不明白struct device 中的parent是什么意思?
最近在写一个光感传感器设备的驱动。不知为何上层的接口是通过input设备实现的。
其实我们自己也可以讲某一个输入设备 如传感器等写为一个字符设备,但是那样的话,我们需要自己实现open\read\write等方法,需要自己实现阻塞。但是通过实现成一个input设备,我们可以把注意力集中到input设备要汇报的事件上面,其他的工作系统已经帮我们完成了。
经过研究,input设备提供给我们的便利 就是它剥离了设备、设备产生的事件、事件的处理 这三者之间的逻辑。
三者的关系本来如下: 设备 ------- >事件----------> 事件的处理-------->上层应用。 其中设备驱动程序负责产生事件,产生的事件由 事件的handler处理,通常handler处理后,再向用户态发送消息,也就说与用户态的交互都有handler完成。设备驱动程序只负责检测并产生事件,产生事件后调用input_event 函数汇报事件。 然后,对于每一个input_dev,都有相应的handler负责处理。 input_dev与handler之间是独立的,也就是说一个input_dev 提交的 事件,会由这个设备上注册的每个handler都进行处理,而一个handler可以注册给多个设备。
input_dev和handler之间的挂钩是通过input_attach_handler函数来实现的,在这个函数中有很严格的匹配条件。内核中实现了evdev_handler和evbug_handler,这两个handler因为限制条件很宽松,所以可以挂接到所有的input_dev。 其中,evbug_handler用于打印消息,相当于是一个调试器,每当input_dev提交事件的时候,事件提交给evbug_handler处理时,evbug_handler都会把事件相关的消息打印出来。
evdev_handler是用于与用户态交互的,evdev_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,};
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};
在evdev_handler中实现了connect、disconne函数等,分别实现handler与input_dev的挂接。其中,evdev_fops实现了完整的文件打开、读写等操作。值得重点一提。
首先,在input_init函数中, 有: err = register_chrdev(INPUT_MAJOR, "input", &input_fops); 其中,input_fops中有:
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;lock_kernel();/* No load-on-demand here? */handler = input_table[iminor(inode) >> 5];if (!handler || !(new_fops = fops_get(handler->fops))) {err = -ENODEV;goto out;}/* * That's _really_ odd. Usually NULL ->open means "nothing special", * not "no device". Oh, well... */if (!new_fops->open) {fops_put(new_fops);err = -ENODEV;goto out;}old_fops = file->f_op;file->f_op = new_fops;err = new_fops->open(inode, file);if (err) {fops_put(file->f_op);file->f_op = fops_get(old_fops);}fops_put(old_fops);out:unlock_kernel();return err;}
也就是说,当我们通过open /dev/input/ 这个目录下的设备时,都会调用input_open_file这个函数。因为通过register_chrdev这种方法注册的函数体 对于所有的主设备号是INPUT_MAJOR的设备都是通用的。然后,在这个input_open_file中,通过这个 handler = input_table[iminor(inode) >> 5]; 可以得到evdev_handler。这里之所以得到的handler是evdev_handler 而不是其他的handler,是因为其他的handler都没有实现fops函数,内核在handler_register函数中,可以实现过滤。保证这里得到的就是evdev_handler。 因此,在这个input_open_file中,将file->f_ops进行了修改,把file->f_ops 指向了 evdev_handler->ev_fops。这样在 用户态以后调用 read\write等方法时,就会调用到evdev_handler中的方法中。
这里有些像是手动实现了 C++中的虚函数和多态。内核中有许多面向对象的思想,还需要多多领悟。
下面是evdev_read函数:
static ssize_t evdev_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos){struct evdev_client *client = file->private_data;struct evdev *evdev = client->evdev;struct input_event event;int retval;if (count < input_event_size())return -EINVAL;if (client->head == client->tail && evdev->exist && (file->f_flags & O_NONBLOCK))return -EAGAIN;retval = wait_event_interruptible(evdev->wait,client->head != client->tail || !evdev->exist);if (retval)return retval;if (!evdev->exist)return -ENODEV;while (retval + input_event_size() <= count && evdev_fetch_next_event(client, &event)) {if (input_event_to_user(buffer + retval, &event))return -EFAULT;retval += input_event_size();}return retval;}
在这个函数中实现了read时的阻塞。
- input 子系统的分析与学习(一)
- input 子系统的分析与学习(三)-----input子系统中的结构体
- input 子系统的分析与学习(二)
- input子系统学习笔记八 input子系统的详细分析
- input子系统学习笔记八 input子系统的详细分析
- input子系统学习笔记八 input子系统的详细分析
- input子系统分析一
- input子系统分析一
- Linux input子系统分析 ----(一)
- Input子系统的研究与分析
- linux input 子系统分析 一
- linux input 子系统分析 一
- linux input 子系统分析 一
- input子系统(一)
- linux input子系统学习(一)之 input-core
- Linux下的Input子系统(一)
- Linux下的Input子系统(一)
- linux的input子系统(一)
- latex命令替换之\newcommand
- Memcached 工作原理介绍
- 书真是太神奇了的超级玛丽
- iOS获取当前系统的相关信息和在不同的IOS上检测
- 东秦oj1039
- input 子系统的分析与学习(一)
- python 继承
- 感觉还有好多的C++基础知识要去学习
- C++续行符(反斜杠符号)
- 东秦oj1040
- 东秦oj1041
- 东秦oj1042
- bootstrap css选择不同的宽度
- 东秦oj1043