函数原型
#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
参数解释
- fds:指向一个结构体数组的第0个元素的指针,每个数组元素都是一个struct pollfd结构,用于指定测试某个给定的fd的条件
- nfds:表示fds结构体数组的长度
- timeout:表示poll函数的超时时间,单位是毫秒
函数功能
监视并等待多个文件描述符的属性变化
函数返回值
- 返回值小于0,表示出错
- 返回值等于0,表示poll函数等待超时
- 返回值大于0,表示poll由于监听的文件描述符就绪返回,并且返回结果就是就绪的文件描述符的个数
pollfd结构
struct pollfd {
int fd; /* file descriptor */
short events; /* requested events */
short revents; /* returned events */
};
成员变量说明:
- fd:每一个 pollfd 结构体指定了一个被监视的文件描述符,可以传递多个结构体,指示 poll() 监视多个文件描述符。
- events:表示要告诉操作系统需要监测fd的事件(输入、输出、错误),每一个事件有多个取值
- revents:revents 域是文件描述符的操作结果事件,内核在调用返回时设置这个域。events 域中请求的任何事件都可能在 revents 域中返回。
events&revents的取值如下:
注意:
每个结构体的 events 域是由用户来设置,告诉内核我们关注的是什么,而 revents 域是返回时内核设置的,以说明对该描述符发生了什么事件
这些宏相当于每一个占用一个比特位,所以,如果我们要进行设置两个事件,就使用|
操作,另外,当我们去查看事件是否发生的时候,这个时候我们可以使用revents&
事件,如果事件发生了,那么结果大于1。
poll 特点
poll优点
- poll里包含了要监视的event和发生的event,使读写分离,每次循环不需要重新设置,接口使用方便
- poll的文件描述符数量不受限制,一个数组可以开多大,就可以有多少个文件描述符,换句话说,只要内存足够,想开多少就开多少,但是太多了性能也会下降
poll缺点
- 当文件描述符很多的时候,依旧需要使用轮询的方式来获取文件描述符,效率低
- 每次调用poll也需要吧大量的pollfd结构从用户态拷贝至内核中,文件描述符很多事,效率也会很低
- 同时连接的大量客户在一时刻可能只有很少的处于就绪状态,因此随着监视的描述符数量的增长,其效率也会现行下降
示例
用poll监视标准输入:
#include <stdio.h>
#include <unistd.h>
#include <poll.h>
int main()
{
struct pollfd fds;
fds.fd = 0;
fds.events = POLLIN;
while(1)
{
int ret = poll(&fds,1,1000);
if(ret < 0)
{
perror("poll");
continue;
}
if(ret == 0)
{
printf("timeout...
");
continue;
}
if(fds.revents == POLLIN)
{
char buf[1024] = {0};
read(0,buf,sizeof(buf)-1);
printf("stdin: %s
",buf);
}
}
return 0;
}