1、基本知識
poll的機制與select類似,與select在本質上沒有多大差別,管理多個描述符也是進行輪詢,根據描述符的狀態進行處理,但是poll沒有最大文件描述符數量的限制。poll和select同樣存在一個缺點就是,包含大量文件描述符的數組被整體復制于用戶態和內核的地址空間之間,而不論這些文件描述符是否就緒,它的開銷隨著文件描述符數量的增加而線性增大。
2、poll函數
函數格式如下所示:
# include <poll.h>
int poll ( struct pollfd * fds, unsigned int nfds, int timeout);
pollfd結構體定義如下:
struct pollfd {int fd; /* 文件描述符 */short events; /* 等待的事件 */short revents; /* 實際發生了的事件 */} ; 每一個pollfd結構體指定了一個被監視的文件描述符,可以傳遞多個結構體,指示poll()監視多個文件描述符。每個結構體的events域是監視該文件描述符的事件掩碼,由用戶來設置這個域。revents域是文件描述符的操作結果事件掩碼,內核在調用返回時設置這個域。events域中請求的任何事件都可能在revents域中返回。合法的事件如下:
POLLIN 有數據可讀。
POLLRDNORM 有普通數據可讀。
POLLRDBAND 有優先數據可讀。
POLLPRI 有緊迫數據可讀。
POLLOUT 寫數據不會導致阻塞。
POLLWRNORM 寫普通數據不會導致阻塞。
POLLWRBAND 寫優先數據不會導致阻塞。
POLLMSGSIGPOLL 消息可用。
此外,revents域中還可能返回下列事件:
POLLER 指定的文件描述符發生錯誤。
POLLHUP 指定的文件描述符掛起事件。
POLLNVAL指定的文件描述符非法。
這些事件在events域中無意義,因為它們在合適的時候總是會從revents中返回。
使用poll()和select()不一樣,你不需要顯式地請求異常情況報告。
POLLIN | POLLPRI等價于select()的讀事件,POLLOUT |POLLWRBAND等價于select()的寫事件。POLLIN等價于POLLRDNORM |POLLRDBAND,而POLLOUT則等價于POLLWRNORM。例如,要同時監視一個文件描述符是否可讀和可寫,我們可以設置 events為POLLIN |POLLOUT。在poll返回時,我們可以檢查revents中的標志,對應于文件描述符請求的events結構體。如果POLLIN事件被設置,則文件描述符可以被讀取而不阻塞。如果POLLOUT被設置,則文件描述符可以寫入而不導致阻塞。這些標志并不是互斥的:它們可能被同時設置,表示這個文件描述符的讀取和寫入操作都會正常返回而不阻塞。
timeout參數指定等待的毫秒數,無論I/O是否準備好,poll都會返回。timeout指定為負數值表示無限超時,使poll()一直掛起直到一個指定事件發生;timeout為0指示poll調用立即返回并列出準備好I/O的文件描述符,但并不等待其它的事件。這種情況下,poll()就像它的名字那樣,一旦選舉出來,立即返回。
返回值和錯誤代碼
成功時,poll()返回結構體中revents域不為0的文件描述符個數;如果在超時前沒有任何事件發生,poll()返回0;失敗時,poll()返回-1,并設置errno為下列值之一:
EBADF 一個或多個結構體中指定的文件描述符無效。
EFAULTfds 指針指向的地址超出進程的地址空間。
EINTR 請求的事件之前產生一個信號,調用可以重新發起。
EINVALnfds參數超出PLIMIT_NOFILE值。
ENOMEM 可用內存不足,無法完成請求。
3、測出程序
新聞熱點
疑難解答