poll系统调用和selct类似,也是在指定时间内轮询一定数量的文件描述符,以测试其中是否有就绪者。
poll 的原型如下:
int poll(struct pollfd *fds,nfds_ t nfds,int timeout);
struct pollfd
{
int fd; //要监控的描述符
short events; //对应fd描述符要监控的事件POLLIN-可读、 POLLOUT-可写
short revents;//fd描述符在监控调用返回后实际就绪的事件
}
fds:监控的描述符集合
nfds:监控的描述符或者说事件数量,决定了从fds地址处拷贝多少数据到内核进行监控
timeout:超时等待时间-单位毫秒; -1表示阻塞, 0表示非阻塞
返回值:成功返回实际就绪的事件个数;超时返回0;出错返回-1
操作流程
1.定义描述符的事件结构体或者结构体数组,将需要监控的描述符以及事件信息填充到节点中
示例: struct polfd fds[10]; fds[0].fd = 0; fds[0].events = POLLIN;
2.发起监控调用,将有效节点数据拷贝到内核进行监控,超时或者有描述符就绪则调用返回.
监控调用返回前操作: poll会将 监控的结构体节点的revents成员设置为实际就绪的事件
3.监控调用返回后,程序中遍历结构体数组,通过revents成员确定描述符就绪了什么事件,进而进行对应操作
优缺点分析
优点:
poll采用事件结构体的方式对描述符进行监控,相较于select简化了操作流程
poll所能监控的描述符数量没有最大上限限制
缺点:
poll每次监控都还是需要将监控数据从用户态拷贝到内核态进行
pol监控原理与select相同也是在内核中多次遍历处理,导致性能会随着描述符的增多而下降
poll无法直接获取就绪的描述符进行操作,需要遍历监控事件结构体数组通过每个元素的成员变量revents确定描述符就绪了什么事件
poll不支持跨平台,只能类unix操作系统下使用
使用poll对标准写操作描述符进行监控
#include <unistd.h>
#include <poll.h>
#include <stdio.h>
int main()
{
struct pollfd fds[10];
fds[0].fd = 0;
fds[0].events = POLLIN;
while (1)
{
int ret = poll(fds, 1, 3000);
if (ret < 0)
{
perror("poll");
return -1;
}
if (ret == 0)
{
printf("time out\n");
continue;
}
for (int i = 0; i < 10; ++i)
{
//读事件
if (fds[i].revents == POLLIN)
{
char buf[1024] = {0};
read(fds[0].fd, buf, 1023);
printf("%s\n");
}
else if(fds[i].revents == POLLOUT)
{
//...写事件
}
}
}
return 0;
}