zoukankan      html  css  js  c++  java
  • select,poll和epoll IO复用函数的比较

    三种IO复用函数的区别

      事件/fd集合:

        select:用户分别传入注册的可读,可写和异常事件对应的fd集合(内置数组,封装成一个结构体),内核对fd集合进行在线修改后返回给用户,通知用户fd上实际发生了哪种事件;fd集合没有将fd和事件绑定,需要提供三个fd集合分别传入和输出可读,可写和异常事件

        poll:用户传入一个可变长数组,数组元素为结构体(含文件描述符fd,注册的事件events,实际发生的事件revents);内核对revents进行修改反馈给用户,通知用户fd上实际发生了哪些事件;将fd和事件绑定到一起,任何事件都被统一处理;

        epoll:内核维护一个事件表,用户传入一棵红黑树(其元素为一个结构体,内含事件类型和fd),通过红黑树向事件表中添加,删除和修改事件,内核对事件表进行修改,然后将从事件表中取出实际发生的事件复制到链表中(其元素为一个和结构体,内含事件类型和fd);

      监听的fd的数量:

        select:使用内置数组标识fd集合,由于内置数组的限制,有最大值限制;

        poll:使用可变长数组(vector?有对这里有深入研究的欢迎评论留言指点迷津)表示fd和事件组成的结构体的集合,监听数量可达到65535;

        epoll:使用红黑树表示fd和事件组成的结构体的集合,监听数量可达到65535;

      是否需要重复初始化fd集合:

        select:内核对fd集合进行在线修改,应用程序下次调用都要重置fd集合;

        poll:events 字段设置待检测事件, revents 字段去检测就绪的事件,内核修改结构体的revents成员,而events成员保持不变,应用程序下次调用时不需要重置events成员

        epoll:内核修改事件表进而修改链表(events),而红黑树保持不变,应用程序下次调用时不许重置红黑树(event);

      对实际发生的事件对应的fd集合的处理方式:

        select和poll采用轮询的机制,每次调用都要扫描整个注册的fd集合,检测就绪的fd,检测就绪事件的时间复杂度为O(n);epoll采用的是回调的方式,内核检测到就绪的fd,将触发回调函数,回调函数将fd上对应的事件插入双向链表,最后再将其内容拷贝到用户空间,其检测就绪事件的时间复杂度为O(1)。

        select:返回整个用户注册的事件的集合,用户程序需要要通过遍历内置数组来检测就绪事件(轮询方式);

        poll:返回整个用户注册的事件的集合,用户程序需要通过遍历revevts来检测就绪事件(轮询方式);

        epoll:返回实际发生的事件(含事件类型和fd),用户程序通过回调方式检测就绪事件;

      工作模式:

        select:fd为水平触发模式;

        poll:fd为水平触发模式;

        epoll:fd为水平触发模式或者边缘触发模式。

      使用场景:

         当活动连接比较多时,epoll的效率不一定比poll和select高,因为epoll需要多次触发回调函数;epoll适用于连接数多而活动连接少的情况。

    三种IO复用函数的相同之处

      均可同时监听多个fd,并且等待指定的超时时间,直到一个或多个fd上有事件发生,返回就绪的fd的数量。                                                         

    总结

      select: fd受限,内置数组的形式使得select的最大fd数量受限于FD_SIZE;

            重复初始化,调用select之前需重新初始化fd集合,将fd集合从用户态拷贝到内核态;调用select之后,将fd集合从内核态拷贝到用户态;

          轮询排查,将内核修改过的fd集合返回给用户;

      poll:解决的fd受限(可变长数组)和重复初始化(数组元素为结构体,结构体元素为fd,注册的事件,实际发生的事件,每增加一个fd,就向数组中加入一个结构体,结构体只需要拷贝一次到内核态)的问题;未解决轮询排查的问题;

      epoll:解决了上述三个问题(红黑树)(内核检测到实际发生的事件,将其添加到链表中,不改变红黑树的结构)(将实际发生的事件返回给用户)。
                           

  • 相关阅读:
    Python自学之路-面试题
    k8s学习笔记之三:configmap和secret
    k8s学习笔记之二:Pod
    k8s学习笔记之四:使用kubeadm配置Ingress
    k8s学习笔记之一:使用kubeadm安装k8s集群
    HTTP content-type
    Json对象和Json字符串的区别
    .net 5+ 知新:【2】 .Net Framework 、.Net 、 .NET Standard的概念与区别
    Log4net和Nlog
    通过系统存储过程手动执行SQL Server中的Job
  • 原文地址:https://www.cnblogs.com/yongjin-hou/p/14353370.html
Copyright © 2011-2022 走看看