【Linux】14.IO多路转接之详解poll

目录

poll:地位不如select,因为select可以跨平台,性能又不如epoll

接口函数

int poll(struct pollfd* fds, nfds_t nfds, int timeout);

fds:事件结构数组,poll函数是通过用户传入的事件结构数组进行监控的,也是轮询监控的方式
        如果要监控一个文件描述符,则组织一个事件结构,传递给poll
        如果要监控多个文件描述符,则组织多个事件结构,放到数组当中,传递给poll
时间结构:struct pollfd{…}

struct pollfd
{
	int fd;
	short events;
	short revents;
}

fd:待要监控的文件描述符
events:关心当中文件描述符产生什么事件(可读、可写、异常)
              POLLIN:可读事件
              POLLOUT:可写事件
              如果既关心可读事件也关心可写时间,则将POLLIN | POLLOUT

revents:在poll监控文件描述符的时候,真实产生的事件
               poll在监控的过程当中,文件描述符发生了什么事件,就将该事件放到revents当中

在定义pollfd事件结构体的时候,不需要用户进行初始化,由poll函数进行初始化

小结:
(1)poll函数引入了事件结构数组的方式,对需要内核监控的文件描述符个数是没有限制了。
(2)poll在监控事件结构数组的时候,也是采用轮询遍历的方式进行监控,随着监控的事件结构(文件描述符)的增多,监控轮询效率下降。
(3)用户如果关心一个文件描述符的多种事件(可读、可写、异常),可以直接在同一个事件结构的结构体当中表示,不需要像select一样,添加到不同的事件集合当中去。

nfds:事件结构数组当中有效元素的个数,用来指导poll函数,轮询遍历的范围
eg:struct pollfd arr[10];
        arr[0].fd = 0;
        arr[0].events = POLLIN;

        则:nfds = 1;

timeout:超时时间
               > 0 :带有超时时间的监控,单位:毫秒
               0 :非阻塞的监控方式
               < 0 :阻塞监控的方式

注意区分poll与select的超时时间的传参方式
select的超时时间参数是struct timeval * timeout,需要传入timeval结构体地址。
poll的超时时间参数是int timeout,只需要传入数字即可。

返回值:> 0 :监控成功,返回就绪的文件描述符个数
== 0 :监控超时
< 0 :监控出错

poll的优缺点

优点:
(1)引入了事件结构的方式,用户不需要将关心的事件添加到不同的事件集合当中去。
(2)引用了事件结构的方式,对监控的文件描述符的个数不再限制。
(3)针对和select对比之后,当一次监控成功之后,下一次再次进行监控的时候,不需要重新添加。
缺点:
(1)与select一样也是采用轮询遍历的策略,随着监控的文件描述符增多,轮询效率会下降。
(2)poll不支持跨平台,只能在linux操作系统下使用
(3)在调用poll函数的时候,会将用户组织的事件结构数组,拷贝到内核空间,监控成功之后,会将事件结构数组从内核空间拷贝到用户空间,这个举动比较耗费性能。

poll阻塞监控代码

#include <stdio.h>
#include <unistd.h>
#include <poll.h>

//阻塞  监控 0 号文件描述符

int main()
{
    struct pollfd pf;
    pf.fd = 0;
    pf.events = POLLIN; // 关心可读事件

    poll(&pf, 1, -1); // <0 是阻塞监控

    char buf[1024] = {0};
    read(0, buf, sizeof(buf) - 1);
    printf("buf is : %s\n", buf);

    return 0;
}

【Linux】14.IO多路转接之详解poll
【Linux】14.IO多路转接之详解poll

poll非阻塞监控代码

#include <stdio.h>
#include <unistd.h>
#include <poll.h>

//非阻塞监控 0 号文件描述符

int main()
{
    struct pollfd pf;
    pf.fd = 0;
    pf.events = POLLIN;

    while(1)
    {
        int ret = poll(&pf, 1, 0); //0表示非阻塞
        if(ret < 0)
        {
            perror("poll");
            return 0;
        }
        else if(ret == 0)
        {
            printf("poll timeout\n");
            sleep(1);
            continue; //超时,继续监控
        }

        char buf[1024] = {0};
        read(0, buf, sizeof(buf) - 1);
        printf("buf is : %s\n", buf);
    }
    return 0;
}

【Linux】14.IO多路转接之详解poll

poll超时时间监控代码

#include <stdio.h>
#include <unistd.h>
#include <poll.h>

//超时时间监控0号文件描述符

int main()
{
    struct pollfd pf;
    pf.fd = 0;
    pf.events = POLLIN;

    while(1)
    {
        int ret = poll(&pf, 1, 1); 
        if(ret < 0)
        {
            perror("poll");
            return 0;
        }
        else if(ret == 0)
        {
            printf("poll timeout\n");
            sleep(1);
            continue;
        }

        char buf[1024] = {0};
        read(0, buf, sizeof(buf) - 1);
        printf("buf is :%s\n", buf);
    }
    return 0;
}
上一篇:R语言中set.seed函数的作用


下一篇:APC 篇—— APC 执行