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()
的作用相同。