使用非阻塞?I/O?的應用程序常常使用?poll, select,?每個允許一個進程來決定它是否可讀或者寫一個或多個文件而不阻塞.?這些調用也可阻塞進程直到任何一個給定集合的文件描述符可用來讀或寫.?因此,?它們常常用在必須使用多輸入輸出流的應用程序,?而不必粘連在它們任何一個上.
select poll epoll詳解,支持這些調用都需要來自設備驅動的支持.?這個支持由驅動的?poll?方法調用.?這個方法由下列的原型:
unsigned int (*poll) (struct file *filp, poll_table *wait);
內核驅動是什么意思。這個驅動方法被調用,?無論何時用戶空間程序進行?poll, select,?系統調用,?涉及一個和驅動相關的文件描述符.?這個設備方法負責這?2?步:
- 1.?在一個或多個可指示查詢狀態變化的等待隊列上調用?poll_wait.?如果沒有文件描述符可用作?I/O,?內核使這個進程在等待隊列上等待所有的傳遞給系統調用的文件描述符.
- 2.?返回一個位掩碼,?描述可能不必阻塞就立刻進行的操作.
這?2?個操作常常是直接的,?并且趨向與各個驅動看起來類似.?但是,?它們依賴只能由驅動提供的信息,?因此,?必須由每個驅動單獨實現.
poll_table?結構,?給?poll?方法的第?2?個參數,?在內核中用來實現?poll, select調用;?它在?中聲明,?這個文件必須被驅動源碼包含.?驅動編寫者不必要知道所有它內容并且必須作為一個不透明的對象使用它;?它被傳遞給驅動方法以便驅動可用每個能喚醒進程的等待隊列來加載它,?并且可改變?poll?操作狀態.?驅動增加一個等待隊列到?poll_table?結構通過調用函數?poll_wait:
?void poll_wait (struct file *, wait_queue_head_t *, poll_table *);
poll?方法的第?2?個任務是返回位掩碼,?它描述哪個操作可馬上被實現;?這也是直接的.?例如,?如果設備有數據可用,?一個讀可能不必睡眠而完成; poll?方法應當指示這個時間狀態.?幾個標志(通過?定義)用來指示可能的操作:
POLLIN
如果設備可被不阻塞地讀,?這個位必須設置.
POLLRDNORM
這個位必須設置,?如果"正常"數據可用來讀.?一個可讀的設備返回( POLLIN|POLLRDNORM ).
POLLRDBAND
這個位指示帶外數據可用來從設備中讀取.?當前只用在?Linux?內核的一個地方( DECnet?代碼?)并且通常對設備驅動不可用.
POLLPRI
高優先級數據(帶外)可不阻塞地讀取.?這個位使?select?報告在文件上遇到一個異常情況,?因為?selct?報告帶外數據作為一個異常情況.
POLLHUP
當讀這個設備的進程見到文件尾,?驅動必須設置?POLLUP(hang-up).?一個調用?select?的進程被告知設備是可讀的,?如同?selcet?功能所規定的.
POLLERR
一個錯誤情況已在設備上發生.?當調用?poll,?設備被報告位可讀可寫,?因為讀寫都返回一個錯誤碼而不阻塞.
POLLOUT
這個位在返回值中設置,?如果設備可被寫入而不阻塞.
POLLWRNORM
這個位和?POLLOUT?有相同的含義,?并且有時它確實是相同的數.?一個可寫的設備返回( POLLOUT|POLLWRNORM).
POLLWRBAND
如同?POLLRDBAND ,?這個位意思是帶有零優先級的數據可寫入設備.?只有?poll?的數據報實現使用這個位,?因為一個數據報看傳送帶外數據.
應當重復一下?POLLRDBAND?和?POLLWRBAND?僅僅對關聯到?socket?的文件描述符有意義:?通常設備驅動不使用這些標志.
static unsigned int mem_p_poll(struct file *filp, poll_table *wait) { struct mem_dev *dev = filp->private_data;unsigned int mask = 0;poll_wait(filp, &dev->my_queue, wait); /* Ъ/if(dev->wr_flag) // Mmask = POLLIN |POLLRDNORM;elsemask = POLLOUT | POLLWRNORM;return mask; }
?