poll機制就是給定一段時間,在這一段時間內程序處於睡眠狀態一直等待某一個資源,它會在兩種狀況下返回①時間到了②等到了資源。函數
驅動程序的實現並不複雜,但原理有待分析。測試
首先要在file_operation裏添加.poll = forth_drv_poll,而後pwa
unsigned int forth_drv_poll(struct file *file,poll_table *wait)隊列
{ unsigned int mask = 0;進程
poll_wait(file,&button_waitq,wait);事件
//不會馬上休眠 資源
if(ev_press)回調函數
mask |= POLLIN | POLLRDNORN; it
return mask;io
}
當應用程序調用poll()時,對應系統調用sys_poll(),而後執行 do_sys_poll ()再以後是 poll_initwait();在poll_initwait()中註冊一下回調函數__pollwait,它就是咱們的驅動程序執行poll_wait()時,真正被調用的函數。
再執行do_poll(),在這個函數裏有一個死循環
do_poll(nfds, head, &table, end_time);
for(;;)
{
for (; pfd != pfd_end; pfd++) //查詢多個驅動程序
{
if (do_pollfd(pfd, pt)) -> mask = file->f_op->poll(file, pwait);return mask;
{ //do_pollfd函數至關於調用驅動裏面的forth_drv_poll函數,下面另外再進行分析,返回值mask非零,count++,記錄等待事件發生的進程數
count++;
pt = NULL;
}
}
if (count || timed_out) //若count不爲0(有等待的事件發生了)或者timed_out不爲0(有信號發生或超時),則推出休眠
break;
//上述條件不知足下面開始進入休眠,如有等待的事件發生了,超時或收到信號則喚醒
poll_schedule_timeout(wait, TASK_INTERRUPTIBLE, to, slack)
}
而後總結一下整個驅動程序的流程:
先把部分測試程序貼出來:
while(1){
ret = poll(fds,1,5000);
if(ret == 0)
{
printf("time out \n");
}
else
{
read(fd,&key_values,1);
printf("key_value = 0x%x\n",key_values);
}
}
當程序執行poll()的時候,會發生如上所示的過程,當執行到驅動程序的forth_drv_poll()時,會把進程放到button_waitq隊列裏,但不會馬上休眠,同時mask的值仍然是0.因此count不能執行加1,因此就不知足break的條件,而後執行休眠_timeout的命令。
①若是在time_out的時間結束了尚未發生中斷,此時仍處於死循環for中,但時間已經用完,因此當在執行到break的條件是會獲得知足,那麼就會跳出for死循環,同時poll()函數返回0,再打印出「time out」;
②若是在在time_out的時間內發生了中斷,在中斷處理函數中,就會把中斷事件標誌置1,而後把進程喚醒,同時獲得按鍵的值,中斷處理完成後又會回到for死循環中,再次執行驅動程序的forth_drv_poll()函數,此時因爲中斷事件標誌爲1,因此會返回一個非零的mask,進而count++,打破break跳出死循環,而後poll()返回一個非零的ret同時在接下來執行read函數,得到鍵值以後,將鍵值打印出來。
這就是poll機制的一個例子。