前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >select/poll/epoll 对比分析

select/poll/epoll 对比分析

作者头像
Yif
发布2019-12-26 14:49:07
1K0
发布2019-12-26 14:49:07
举报
文章被收录于专栏:Android 进阶Android 进阶

select

原型:

代码语言:javascript
复制
int select (int maxfd, fd_set *readfds, 
                   fd_set *writefds, 
                   fd_set *exceptfds, 
                   struct timeval *timeout);
  • maxfd:代表要监控的最大文件描述符fd+1
  • writefds:监控可写fd
  • readfds:监控可读fd
  • exceptfds:监控异常fd
  • timeout:超时时长
    • NULL,代表没有设置超时,则会一直阻塞直到文件描述符上的事件触发
    • 0,代表不等待,立即返回,用于检测文件描述符状态
    • 正整数,代表当指定时间没有事件触发,则超时返回

select函数监控3类文件描述符,调用select函数后会阻塞,直到描述符fd准备就绪(有数据可读、可写、异常)或者超时,函数便返回。 当select函数返回后,可通过遍历描述符集合,找到就绪的描述符。

select缺点

  • 文件描述符个数受限:单进程能够监控的文件描述符的数量存在最大限制,在Linux上一般为1024,可以通过修改宏定义增大上限,但同样存在效率低的弱势;
  • 性能衰减严重:IO随着监控的描述符数量增长,其性能会线性下降;

poll

原型:

代码语言:javascript
复制
int poll (struct pollfd *fds, unsigned int nfds, int timeout);

其中pollfd表示监视的描述符集合,如下

代码语言:javascript
复制
struct pollfd {
    int fd; //文件描述符
    short events; //监视的请求事件
    short revents; //已发生的事件
};

pollfd结构包含了要监视的event和发生的event,并且pollfd并没有最大数量限制。 和select函数一样,当poll函数返回后,可以通过遍历描述符集合,找到就绪的描述符。

poll缺点

selectpoll都需要在返回后,通过遍历文件描述符来获取已经就绪的socket。同时连接的大量客户端在同一时刻可能只有很少的处于就绪状态,因此随着监视的描述符数量的增长,其性能会线性下降。

select 和 poll 比较

功能

selectpoll 的功能基本相同,不过在一些实现细节上有所不同。

  • select 会修改描述符,而 poll 不会;
  • select 的描述符类型使用数组实现,FD_SETSIZE 大小默认为 1024,因此默认只能监听 1024 个描述符。如果要监听更多描述符的话,需要修改 FD_SETSIZE 之后重新编译;而 poll 的描述符类型使用链表实现,没有描述符数量的限制;
  • poll 提供了更多的事件类型,并且对描述符的重复利用上比 select 高。
  • 如果一个线程对某个描述符调用了 select 或者 poll,另一个线程关闭了该描述符,会导致调用结果不确定。

速度

selectpoll 速度都比较慢。

  • selectpoll 每次调用都需要将全部描述符从应用进程缓冲区复制到内核缓冲区。
  • selectpoll 的返回结果中没有声明哪些描述符已经准备好,所以如果返回值大于 0 时,应用进程都需要使用轮询的方式来找到 I/O 完成的描述符。

epoll

epoll是在内核2.6中提出的,是selectpoll的增强版。相对于selectpoll来说, epoll更加灵活,没有描述符数量限制。epoll使用一个文件描述符管理多个描述符,将用户空间的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的copy只需一次。epoll机制是Linux最高效的I/O复用机制,在一处等待多个文件句柄的I/O事件。

select/poll都只有一个方法,epoll操作过程有3个方法,分别是epoll_create()epoll_ctl()epoll_wait()

epoll_create

代码语言:javascript
复制
int epoll_create(int size);

功能:用于创建一个epoll的句柄,size是指监听的描述符个数, 现在内核支持动态扩展,该值的意义仅仅是初次分配的fd个数,后面空间不够时会动态扩容。 当创建完epoll句柄后,占用一个fd值.

代码语言:javascript
复制
ls /proc/<pid>/fd/  //可通过终端执行,看到该fd

使用完epoll后,必须调用close()关闭,否则可能导致fd被耗尽。

epoll_ctl

代码语言:javascript
复制
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

功能:用于对需要监听的文件描述符(fd)执行op操作,比如将fd加入到epoll句柄。

  • epfd:是epoll_create()的返回值;
  • op:表示op操作,用三个宏来表示,分别代表添加、删除和修改对fd的监听事件;
    • EPOLL_CTL_ADD(添加)
    • EPOLL_CTL_DEL(删除)
    • EPOLL_CTL_MOD(修改)
  • fd:需要监听的文件描述符;
  • epoll_event:需要监听的事件,struct epoll_event结构如下: struct epoll_event {   __uint32_t events;  /* Epoll事件 */   epoll_data_t data;  /*用户可用数据*/ };
  • events可取值:(表示对应的文件描述符的操作)
    • EPOLLIN :可读(包括对端SOCKET正常关闭);
    • EPOLLOUT:可写;
    • EPOLLERR:错误;
    • EPOLLHUP:中断;
    • EPOLLPRI:高优先级的可读(这里应该表示有带外数据到来);
    • EPOLLET: 将EPOLL设为边缘触发模式,这是相对于水平触发来说的。
    • EPOLLONESHOT:只监听一次事件,当监听完这次事件之后就不再监听该事件

epoll_wait

代码语言:javascript
复制
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);

功能:等待事件的上报

  • epfd:等待epfd上的io事件,最多返回maxevents个事件;
  • events:用来从内核得到事件的集合;
  • maxevents:events数量,该maxevents值不能大于创建epoll_create()时的size
  • timeout:超时时间(毫秒,0会立即返回)。

该函数返回需要处理的事件数目,如返回0表示已超时。

三者对比

select/poll中,进程只有在调用一定的方法后,内核才对所有监视的文件描述符进行扫描,而epoll事先通过epoll_ctl()来注册一个文件描述符,一旦基于某个文件描述符就绪时,内核会采用类似callback的回调机制,迅速激活这个文件描述符,当进程调用epoll_wait() 时便得到通知。(此处去掉了遍历文件描述符,而是通过监听回调的的机制。这正是epoll的魅力所在。

epoll优势

  1. 监视的描述符数量不受限制,所支持的FD上限是最大可以打开文件的数目,具体数目可以cat /proc/sys/fs/file-max查看,一般来说这个数目和系统内存关系很大,以3G的手机来说这个值为20-30万。
  2. IO性能不会随着监视fd的数量增长而下降。epoll不同于selectpoll轮询的方式,而是通过每个fd定义的回调函数来实现的,只有就绪的fd才会执行回调函数。

总结

  1. 如果没有大量的空闲或者死亡连接,epoll的效率并不会比select/poll高很多。但当遇到大量的空闲连接的场景下,epoll的效率大大高于select/poll
  2. select/poll/epoll都是IO多路复用机制,可以同时监控多个描述符,当某个描述符就绪(读或写就绪),则立刻通知相应程序进行读或写操作。本质上select/poll/epoll都是同步I/O,即读写是阻塞的。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年7月18日 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • select
    • select缺点
    • poll
      • poll缺点
      • select 和 poll 比较
        • 功能
          • 速度
          • epoll
            • epoll_create
              • epoll_ctl
                • epoll_wait
                • 三者对比
                  • epoll优势
                  • 总结
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档