linux man中
poll
的翻譯,poll
在設計上解決了select
可監聽描述符的個數限制,但在一些系統中兼容性並不是很好,因此還是建議使用select
來實現簡單socket
應用,翻譯此文僅對epoll()
的學習做一個鋪墊。
名字
poll - 等待描述符上的事件
摘要
#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
描述
poll
的行爲與 select
相似:它等待直到描述符集準備好進行I/O操作。
被監控的描述符集由參數 fds
指定,這個參數是一個結構體數組,結構體如下:
struct pollfd {
int fd; /* file descriptor */
short events; /* requested events */
short revents; /* returned events */
};
調用時需要應用 nfds
參數指定 fds
數組中元素的個數。
fd
是一個已經打開的文件的描述符。如果這個參數爲負值, 與 events
的通信將被忽略,同時 revents
將返回 0(這爲在一次poll()
調用中忽略某個文件描述符提供了簡潔的辦法,即將 fd
置爲負數即可,但注意此方法不能忽略描述符0)。
events
是一個輸入域,它以位掩碼的方式來指定文件描述符fd
需要監測的事件,這個變量可以被置爲0,這時可以返回的是事件只有POLLHUP/POLLERR/POLLNVAL(見下文)。
revents
是一個輸出域,由內核賦值當前發生的事件。revents
返回events
中指定的事件之一,或者POLLHUP/POLLERR/POLLNVAL事件(這三位在events
中是沒有意義的,當發生條件爲ture
時則在revents
中被置爲1)。
如果在任何文件描述符中都沒有事件響應,則poll()
將被阻塞直到有事件發生。
timeout
參數指定poll()
等待直到有文件描述符爲ready
狀態的超時時間,在滿足以下條件時調用將被返回:
- 文件描述符變爲
ready
狀態 - 調用被信號處理打斷
- 等待超時
注意超時間隔以系統時鐘爲原子單位,內核調度延遲意味着阻塞間隔將較少的超出實際間隔。賦值一個負數將會導致一直阻塞。賦值爲0則將會立即返回,即使在沒有事件ready
的狀態下。
在<poll.h>
中定義了events
和revents
中可以設置和返回的位:
- POLLIN:可進行讀取操作
- POLLPRI:緊急的數據
ready
(如:TCP的out-of-band數據) - POLLOUT:可進行寫入操作,然而在
socket
或這pipe
如果寫入超過可以利用空間的數據將導致阻塞。 - POLLRDHUP(Linux 2.6.17及以上版本):
socket
流的同伴closed
連接,或者在寫入未完成時shut down
。應用時需要保證_GUN_SOURCE
宏定義被定義 - POLLERR:條件錯誤(只在
revents
中被返回,在events
中被忽略) - POLLHUP:掛起(只在
revents
中被返回,在events
中被忽略),注意當在socket
或pipe
等信道中讀取時,這個事件僅僅用來指示socket或pipe的夥伴在文件末尾被closed
。 在未讀取的數據被讀取之後,接下來的讀取事件將返回0。 - POLLNVAL:不合法的請求:
fd
未打開(只在revents
中被返回,在events
中被忽略)
返回值
成功時返回正數,返回值就是revent
中的非零值。超時時返回0。錯誤時會返回-1,並且在errno
中設置了錯誤碼。
錯誤
EBADF
- 指定需要檢測的文件描述符集不合法(一個已經關閉的描述符,或者一個出現錯誤的描述符)
EINTR
- 信號被捕捉,詳見 signal
EINVAL
- nfds
是負數或者 timeout
中的值不合法
ENOMEM
- 不能爲內部表分配內存
版本
2.1.23及以上
ppoll()
int ppoll(struct pollfd *fds, nfds_t nfds,
const struct timespec *tmo_p, const sigset_t *sigmask);
poll()
和 ppoll()
與 select()
和 pselect()
的作用相同。