IO多路复用之poll

IO多路复用之poll

前面我们看到了select有很多的缺点,这里我们再来认识一下poll:

函数原型:
这里写图片描述
这里第一个参数中的fds实际上是一个struct pollfd的数组,数组中的每个元素代表一个文件描述符,下面是poolfd结构体的原型,其中第一个成员表示所要关注的文件描述符,第二个成员表示要关注的就绪事件,第三个成员代表返回的就绪事件。
这里写图片描述
第二个参数表示这个数组的长度,即要关注的文件描述符的个数
第三个参数表示超时时间,单位是毫秒。负数表示无限等待,0表示不等待直接返回,正数表示要等待的最小时间。

我们使用poll完成对标准输入读状态就绪的等待:

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

int main()
{
  struct pollfd fds;
  fds.fd=0;
  fds.events=POLLIN;
  while(1)
  {
    int ret=poll(&fds,1,-1);
    if(ret<0)
    {
      perror("poll");
      return 1;
    }
    char buf[1024]={0};
    ssize_t read_size=read(0,buf,sizeof(buf)-1);
    if(read_size<0)
    {
      perror("read");
      return 1;
    }
    if(read_size==0)
    {
      printf("read done\n");
      return 0;
    }
    buf[read_size]='\0';
    printf("%s\n",buf);
  }
  return 0;
}

输入输出进行分离
poll的优点

  • 使用pollfd这样的结构体来表示一个文件描述符的状态,其中使用events和revents将输入和输出进行分离,比起select中输入输出都体现在一个参数上,输出每次会覆盖输入,poll解决了这一问题。
  • 解决了select中文件描述符数量被限制的问题

poll的缺点

  • 每次调用poll时,还是得重新传所有的文件描述符
  • 每次调用poll,也要从用户态拷贝到内核态,并且拷贝的数据相比select远远增多,select中每个文件描述符只拷贝一位,而poll要拷一个结构体,文件描述符很多时,开销非常大,效率更低。
  • 与select一样,不论是从用户拷到内核还是从内核拷到用户,都要进行遍历。

猜你喜欢

转载自blog.csdn.net/shidantong/article/details/81048018