linux系统下select和poll的实现机理
1.用户层应用程序调用select()
2.核心层调用sys_select()------>do_select()
最终调用文件描述符fd对应的structfile类型变量的structfile_operations*f_op的poll函数。
poll指向的函数返回当前可否读写的信息。
1)如果当前可读写,返回读写信息。
2)如果当前不可读写,则阻塞进程,并等待驱动程序唤醒,重新调用poll函数,或超时返回。
核心层的相关函数(select.c):
do_select(...)
{
poll_table*wait;
...
for(;;)
{
set_current_state(TASK_INTERRUPTIBLE);
for(i=0;i<n;i++)
{
unsignedlongmask;
structfile*file;
...
file=fget(i);
mask=POLLNVAL;
mask=file->f_op->poll(file,wait);
if((mask&POLLIN_SET)&&ISSET(bit,__IN(fds,off)))
retval++;
if((mask&POLLOUT_SET)&&ISSET(bit,__OUT(fds,off))){
retval++;
}
if(retval||!__timeout||signal_pending(current))
break;
__timeout=schedule_timeout(__timeout);//此处阻塞,等待驱动wake_up_interruptible
}
current->state=TASK_RUNNING;
}
3.驱动需要实现poll函数。
当驱动发现有数据可以读写时,通知核心层,核心层重新调用poll指向的函数查询信息。
例如:
staticunsignedinttest_poll(structfile*file,poll_table*wait)
{
poll_wait(file,&queue,wait);//此处将当前进程加入到等待队列中,但并不阻塞
returnPOLLIN|POLLRDNORM|...;
}
staticvoidtest_...(...)
{
wake_up_interruptible(&queue->proc_list);
}
staticvoidtest_init(...)
{
init_waitqueue_head(&queue->proc_list);
}