函数原型

#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);

参数解释

fds:指向一个结构体数组的第0个元素的指针,每个数组元素都是一个struct pollfd结构,用于指定测试某个给定的fd的条件
nfds:表示fds结构体数组的长度
timeout:表示poll函数的超时时间,单位是毫秒

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的取值如下:

poll-风君雪科技博客

注意:
每个结构体的 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;
}