天天看點

select 和poll函數調用驅動的poll->poll_wait 了解

poll_wait不會挂起目前程序,而是把自己注冊到某個事件等待隊列中.

poll_wait()是用在select系統調用中的. 

一般你的代碼會有一個struct file_operations結構, 

其中fop->poll函數指針指向一個你自己的函數, 

在這個函數裡應該調用poll_wait() 

當使用者調用select系統調用時,select系統調用會 

先調用 

poll_initwait(&table); 

然後調用你的 

fop->poll(); 

進而将current加到某個等待隊列(這裡調用poll_wait()), 

并檢查是否有效 

如果無效就調用 

schedule_timeout(); 

去睡眠. 

事件發生後,schedule_timeout()回來,調用 

檢查到可以運作,就調用 

poll_freewait(&table); 

進而完成select系統調用. 

重要的是fop->poll()裡面要檢查是否就緒, 

如果是,要傳回相應标志 

挂起與否是在sys_select()或sys_poll()兩個系統調用中根據 

使用者傳入的timeout和fd的具體情況決定的,是這兩個系統調用 

将程序挂起的 

你的file_operation-->poll()隻需要調用poll_wait(),并判斷是否就緒, 

如果就緒就設定标志,這樣即可.

假設我沒有使用timeout,也沒有signal 

我隻關心writeable事件,但是裝置在poll時總傳回POLLRD事件, 

那麼就會出現這種情況啊,不停的加poll_entry成員到睡眠隊列,總有一天會溢出 啊。

不會啊,因為如果沒有timeout和signal,它不會醒的, 

隻要他醒了,隻有三種可能: 

1,timeout 

2,signal 

3,裝置就緒

如果目前不可讀,那麼在sys_poll->do_poll中目前程序就會睡眠在等待隊列上,這個等待隊列是由驅動程式提供的(就是poll_wait中傳入的那個)。當可讀的時候,驅動程式可能有一部分代碼運作了(比如驅動的中斷服務程式),那麼在這部分代碼中,就會喚醒等待隊列上的程序,也就是之前睡眠的那個,當那個程序被喚醒後do_poll會再一次的調用驅動程式的poll函數,這個時候應用程式就知道是可讀的了。