Linux驱动基本理论之——poll机制图解
poll(轮询)操作在应用程序中用于同时阻塞在多个文件上,当其中任何一个文件有应用程序所等待的事件(可读、可写、出错等)时,poll返回相应的掩码通知应用程序,使得应用程序知道应该对哪个文件做何种操作。按照我的理解,poll的本质可以这样解释:休眠等待多个指定文件中的任何一个发生特定的事件,并将被该文件唤醒;醒来后轮询所有相关文件(通过再次调用所有文件对应驱动的poll方法),获取所有被监控文件的事件信息返回给应用程序。
从这里就可以看出:
(1)其中等待队列的使用是必不可少的。实际上调用poll的进程将会休眠在多个等待队列(一般所有被监控文件的都有至少一个的等待队列)上,从其中任何一个队列上唤醒该进程,都可能使poll函数返回。
(2)驱动中的poll方法不实现休眠,而是:
i、把当前进程添加到相应的等待队列中(仅在休眠时执行,唤醒时不会执行此功能)。
ii、返回文件当前的状态掩码(告知是否有事件发生,休眠和唤醒都会执行)。
对于等待队列的情况,我用下面一个例子和图来示意一下:
例如有3个进程:
task-1:使用poll检测文件1~3
task-2:使用poll检测文件2~3
task-3:使用poll检测文件3
则等待队列的情况如下:
之后,假设task-2由于文件2或3被唤醒,且task-1/3对此不感兴趣(未设置该掩码),那么等待队列的情况如下:
等待队列入口项的添加和删除主要是由poll_initwait(&table);和poll_freewait(&table);完成。
poll_initwait(&table);完成初始化struct poll_wqueues table的工作,而poll_freewait(&table);负责清理这个结构体。这里需要注意的是等待队列中的wait_queue_t并不是在唤醒函数pollwake从队列中删除的,而是最后由poll_freewait(&table);集中处理的。而唤醒函数和普通的wait_event的唤醒函数有很大不同,