poll, ppoll
poll,ppoll
poll, ppoll - 等待文件描述符的一些事件
SYNOPSIS
#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <signal.h>
#include <poll.h>
int ppoll(struct pollfd *fds, nfds_t nfds,
const struct timespec *timeout_ts, const sigset_t *sigmask);
DESCRIPTION
poll() 类似于select,等待一组文件描述符直到I/O处于可用状态
这组文件描述符是fds数组传入的,成员结构如下:
struct pollfd {
int fd; /* 文件描述符 */
short events; /* 请求事件 */
short revents; /* 返回事件 */
};
调用者必须通过nfds参数指出fds数组成员的个数.
fd是已经打开的文件的文件描述符,如果fd不可用,或者是非法的,在结构中给出的events会被忽略,同时revents返回0(这样做提供了一个在调用poll函数时忽略文件描述符的简单方法.(使文件描述符无效,就可以在poll的时候忽略掉该fds成员的监控,注意:不能把fd设置成0);
events:是一个输入型参数,每个bit位指定一个和fd相关的事件,events可以是0,当events是0的时候,revents只能返回三种事件POLLHUP, POLLERR, POLLNVAL.
revents:是一个输出型参数,内核根据实际发生的事件来填写revents,revents可以返回任何一个在events中填写的事件,或者是POLLERR, POLLHUP, POLLNVAL中的一个.
如果所有fds中的数组成员指定的events中请求的事件都没有发生,poll()将一直阻塞,直到有事件发生.
timeout:指定在没有事件发生时,可以阻塞多少毫秒(ms).
注意:由于每个系统的系统时钟的问题,实际阻塞的时间可能会超出timeout指定的时间. 如果设置timeout为负值,意味着poll将一直等待下去,直到事件发生.如果设置为0,poll会立即返回,不管事件是否发生和.
在events和revents中的bit位定义在<poll.h>中
POLLIN
有数据可读
POLLPRI
有紧急的数据要读.(通过send可以设置收取的是否为紧急数据)
http://www.masterraghu.com/subjects/np/introduction/unix_network_programming_v1.3/ch24lev1sec2.html
POLLOUT
可以写入,但如果没有把fd设置成O_NONBLOCK,较大的数据将会继续阻塞.
POLLRDHUP (since Linux 2.6.17)
socket链接的对端关闭了链接,或者是链接异常.
POLLERR
poll函数异常
POLLHUP
poll函数挂起
POLLNVAL
fd没有打开.(socket或者文件没有被打开,或者不存在)
在编译时定义了 _XOPEN_SOURCE, 会有下面的事件
POLLRDNORM
等同于POLLIN
POLLWRNORM
等同于POLLOUT
POLLWRBAND
优先数据可以写入
ppoll()
poll和ppoll很相似,就像select和pselect.ppoll允许程序安全的等待,直到文件描述符已经准备好了,或者捕捉到一个退出的信号.
在timeout参数上,ppoll比poll精确.
ready = ppoll(&fds, nfds, timeout_ts, &sigmask);
上面的函数函数调用相当于执行下面的代码:
sigset_t origmask;
int timeout;
timeout = (timeout_ts == NULL) ? -1 :
(timeout_ts.tv_sec * 1000 + timeout_ts.tv_nsec / 1000000);
sigprocmask(SIG_SETMASK, &sigmask, &origmask);
ready = poll(&fds, nfds, timeout);
sigprocmask(SIG_SETMASK, &origmask, NULL);
查看pselect,理解ppoll为什么是首选.
如果sigmask参数是NULL, ppoll不会监控任何事件,和poll唯一的区别就是timeout参数.
timeout_ts参数给出一个ppoll阻塞的上限时间.timeout_ts是一个指针,timeout_ts的结构如下:
struct timespec {
long tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
timeout_ts如果是NULL,ppoll将一直阻塞到事件发生.
RETURN VALUE
成功:返回一个正数,返回值为非0的revents的位数.如果返回0,表示ppoll是超时返回.
错误:返回-1,并且会设置系统的errno.
ERRORS
EFAULT The array given as argument was not contained in the calling program's address space.
数组参数不可用
EINTR A signal occurred before any requested event; see signal(7).
捕捉到特殊的信号,具体的信号请查看signal手册.
EINVAL The nfds value exceeds the RLIMIT_NOFILE value.
nfds的数组大小超出了RLIMIT_NOFILE
ENOMEM There was no space to allocate file descriptor tables.
没有空间用于创建文件描述符表
VERSIONS
poll函数在2.1.23之后提供的,在老的内核中没有poll系统调用.在之前的版本可用使用select.
CONFORMING TO
poll遵循POSIX.1-2001,ppoll是linux引入的
NOTES
某些版本会定义非标准的常量INFTIM = -1,用于poll的timeout参数, 在glibc中不支持INFTIM常量.