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);

}