文章目录
- 一:poll函数接口
- 参数说明:
- 返回结果:
- 二:poll的优缺点
- 优点:
- 缺点:
- 三:poll代码示例
一:poll函数接口
#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
我们从struct polled结构体可以看出,该结构体包含三个成员,文件描述符,对该文件描述符关心的事件,返回的该文件描述符对应的准备好的事件。
参数说明:
- fds是一个poll函数监听的结构列表. 每一个元素中, 包含了三部分内容: 文件描述符, 监听的事件集合, 返回的事件集合。
- nfds表示fds数组的长度。
- timeout表示poll函数的超时时间, 单位是毫秒(ms)。
💡events和revents的取值:
返回结果:
- 返回值小于0, 表示出错。
- 返回值等于0, 表示poll函数等待超时。
- 返回值大于0, 表示poll由于监听的文件描述符就绪而返回。
二:poll的优缺点
不同与select使用三个位图来表示三个fd_set的方式,poll使用一个pollfd的指针实现,对应的一个结构体数组。
优点:
- pollfd结构包含了要监视的event和发生的event,不再使用select“参数-值”传递的方式。因为正如struct pollfd结构体所示,poll的特定的sock所关心的事件输入输出进行了分离,不需要再像select一样维护额外的结构记录需要关心的sock,因此接口使用比select更方便。
- poll并没有最大数量限制 (但是数量过大后性能也是会下降),程序员决定数组大小!
缺点:
poll中监听的文件描述符数目增多时:
- 和select函数一样,poll返回后,需要轮询pollfd来获取就绪的描述符,意味着O(N)的遍历复杂度。
- 每次调用poll都需要把大量的pollfd结构从用户态拷贝到内核中。
- 同时连接的大量客户端在一时刻可能只有很少的处于就绪状态, 因此随着监视的描述符数量的增长, 其效率也会线性下降。
三:poll代码示例
使用poll监控标准输入:
#include <poll.h>
#include <unistd.h>
#include <stdio.h>
int main() {
struct pollfd poll_fd;
poll_fd.fd = 0;
poll_fd.events = POLLIN;
for (;;) {
int ret = poll(&poll_fd, 1, 1000);
if (ret < 0) {
perror("poll");
continue;
}
if (ret == 0) {
printf("poll timeout\n");
continue;
}
if (poll_fd.revents == POLLIN) {
char buf[1024] = { 0 };
read(0, buf, sizeof(buf) - 1);
printf("stdin:%s", buf);
}
}
}