在进行 Input 系统分析之前,先简单学习一下 Input 系统和 linux 交互的几个方法,因为 epoll 机制是 InputManagerServer 和 linux 设备节点交互的主要工具。另外只是单存的使用接口,粗略的理解一下其原理,具体 epoll 机制不做深究。目前参考了书籍后整理了一下如下内容。
INotify
INotify 是 Linux 内核所提供的一种文件系统变化的通知机制。可以为应用程序监控文件系统的变化,如:文件的新建、删除、读写等。 INotify 机制有两个基本对象,分别为 inotify 对象和 watch 对象,都使用文件描述符表示。
INotify 对象
inotify 对象可以监听多个事件,当所监听的事件发生时,可以通过 read() 函数从该对象中获取事件信息。创建事件的方法如下:
int inotifyFd = inotify_init();复制代码
watch 对象
watch 对象用来描述需要监听的变化事件,包含两部分,监听目标和监听事件。监听目标是指文件系统当中的一个路径,可以是文件,也可以是文件夹。事件掩码则是文件系统事件的变化类型,比如文件的创建 (IN_CREATE
) 和删除 (IN_DELETE
)。如果我们希望将监听事件的 watch 对象添加进 inotify 对象中,需要使用以下代码:
int wd = inotify_add_watch(inotifyFd, "/dev/input", IN_CREATE | IN_DELETE);复制代码
当我们添加了 watch 对象后,如果 watch 对象所描述的监听事件发生时,可以通过 read() 方式将为读取的事件信息读取出来。
size_t len = read(inotifyFd, events_buf, BUF_LEN);复制代码
Epoll 机制
以 input 系统为例,我们要响应所有的设备类型,就相当于要监听每一个设备节点的 input
事件。那如果采用轮询或者创建线程去读取的话,都会造成资源的极度浪费。这里便可以采用 Epoll 机制。Epoll 机制可以监听多个描述符的可读可写状态。
创建 epoll
对象,这个对象代表了可以监听的描述符的最大数量:
int epfd = epoll_create(MAX_FDS);复制代码
填充结构体,添加进监听列表:
// epfd epoll 对象的描述符// EPOLL_CTL_ADD 添加或者删除的事件操作// listeningFd 监听事件的描述符// eventItem 是一个 epoll_data_t 结构体的实例,result = epoll_ctl(epfd, EPOLL_CTL_ADD, listeningFd, &eventItem);复制代码
等待事件,知道第一个事件发生后才会返回:
epoll_wait(int epfd, stuct epolll_event * events, int maxevents, int timeout);复制代码