poll机制分析
分析
所有的系统调用,基于都可以在它的名字前加上“sys_”前缀,这就是它在内核中对应的函数。比如系统调用open、read、write、poll,与之对应的内核函数为:sys_open、sys_read、sys_write、sys_poll。
一、内核框架:
对于系统调用poll或select,它们对应的内核函数都是sys_poll。分析sys_poll,即可理解poll机制。
1.
asmlinkage
long
{
s64
timeout_jiffies; if
(timeout_msecs > 0) { #if
HZ > 1000
if
(timeout_msecs / 1000 > (s64)0x7fffffffffffffffULL / (s64)HZ) timeout_jiffies
= -1; else
#endif
timeout_jiffies
= msecs_to_jiffies(timeout_msecs); }
else {
timeout_jiffies
= timeout_msecs; }
return
do_sys_poll(ufds,nfds, &timeout_jiffies);
}
它对超时参数稍作处理后,直接调用do_sys_poll。
2.
int
{
……
poll_initwait(&table);
……
fdcount
= do_poll(nfds, head, &table, timeout); ……
}
poll_initwait函数非常简单,它初始化一个poll_wqueues变量table:
poll_initwait
即table->pt->qproc
3.
static
{
01
02
03
04
05 count++;
06pt
07 }
08
09if
10 break;
11count
12if
13 break;
14
15if
16
17__timeout
18}
19
23__timeout
24*timeout
25}
26__timeout
27*timeout
28 }
29
30__timeout
31if
32*timeout
33 }
34__set_current_state(TASK_RUNNING);
35return
36
分析其中的代码,可以发现,它的作用如下:
①
a.
count非0表示04行的do_pollfd至少有一个成功。
b.
②
③
4.
static
{
……
if
(file->f_op && file->f_op->poll) mask
= file->f_op->poll(file, pwait); ……
}
可见,它就是调用我们的驱动程序里注册的poll函数。
二、驱动程序:
驱动程序里与poll相关的地方有两处:一是构造file_operation结构时,要定义自己的poll函数。二是通过poll_wait来调用上面说到的__pollwait函数,pollwait的代码如下:
static
{
if
(p && wait_address) p->qproc(filp,
wait_address, p);
}
p->qproc就是__pollwait函数,从它的代码可知,它只是把当前进程挂入我们驱动程序里定义的一个队列里而已。它的代码如下:
static
poll_table
{
struct
poll_table_entry *entry = poll_get_entry(p); if
(!entry) return;
get_file(filp);
entry->filp
= filp; entry->wait_address
= wait_address; init_waitqueue_entry(&entry->wait,
current); add_wait_queue(wait_address,
&entry->wait);
}
执行到驱动程序的poll_wait函数时,进程并没有休眠,我们的驱动程序里实现的poll函数是不会引起休眠的。让进程进入休眠,是前面分析的do_sys_poll函数的30行“__timeout
poll_wait只是把本进程挂入某个队列,应用程序调用poll
现在来总结一下poll机制:
1.
2.
3.
4.
5.