• 【笔记】select, poll, epool


    Select 系统调用:

      select 轮询监听多个文件描述符的数组,其原理如下(转自:这里):

     

    从用户空间拷贝fd_set到内核空间
    注册回调函数__pollwait;
    遍历所有fd,对全部指定设备做一次poll(这里的poll是一个文件操作,它有两个参数,一个是文件fd本身,一个是当设备尚未就绪时调用的回调函数__pollwait,这个函数把设备自己特有的等待队列传给内核,让内核把当前的进程挂载到其中);
    当设备就绪时,设备就会唤醒在自己特有等待队列中的【所有】节点,于是当前进程就获取到了完成的信号。poll文件操作返回的是一组标准的掩码,其中的各个位指示当前的不同的就绪状态(全0为没有任何事件触发),根据mask可对fd_set赋值;
    如果所有设备返回的掩码都没有显示任何的事件触发,就去掉回调函数的函数指针,进入有限时的睡眠状态,再恢复和不断做poll,再作有限时的睡眠,直到其中一个设备有事件触发为止。
    只要有事件触发,系统调用返回,将fd_set从内核空间拷贝到用户空间,回到用户态,用户就可以对相关的fd作进一步的读或者写操作了。

      上述标红的地方都是比较耗时的,这是select的一大缺陷,此外,select只能监听有限的文件描述符(可修改内核参数)。

      select跨平台特性是其一大优点

    Poll 系统调用

      Poll与Select基本一致,只是没有了监听描述字的个数限制

    Select和Poll都是只支持水平触发

    注:select()和poll()将就绪的文件描述符告诉进程后,如果进程没有对其进行IO操作,那么下次调用select()和poll()的时候将再次报告这些文件描述符,所以它们一般不会丢失就绪的消息,这种方式称为水平触发(Level Triggered)

    epoll 系统调用

      epoll 是linux系统才有的, 几乎具备了之前所说的一切优点,被公认为Linux2.6下性能最好的多路I/O就绪通知方法:转自这里

    epoll支持水平触发和边缘触发(Edge Triggered, 告诉进程哪些文件描述符刚刚发生变为就绪状态,只说一遍,如果进程没有进一步动作,将不会再次告知),

    epoll同样只告知那些就绪的文件描述符,而且当我们调用epoll_wait()获得就绪文件描述符时,返回的不是实际的描述符,而是一个代表就绪描述符数量的值,你只需要去epoll指定的一个数组中依次取得相应数量的文件描述符即可,这里也使用了内存映射(mmap)技术,这样便彻底省掉了这些文件描述符在系统调用时复制的开销。

    另一个本质的改进在于epoll采用基于事件的就绪通知方式在select/poll中,进程只有在调用一定的方法后,内核才对所有监视的文件描述符进行扫描,而epoll事先通过epoll_ctl()来注册一个文件描述符,一旦基于某个文件描述符就绪时,内核会采用类似callback的回调机制,迅速激活这个文件描述符,当进程调用epoll_wait()时便得到通知

      原理:转自这里

    epoll原理概述

    调用epoll_create时,做了以下事情:

    1. 内核帮我们在epoll文件系统里建了个file结点;
    2. 在内核cache里建了个红黑树用于存储以后epoll_ctl传来的socket;
    3. 建立一个list链表,用于存储准备就绪的事件。

    调用epoll_ctl时,做了以下事情:

    1. 把socket放到epoll文件系统里file对象对应的红黑树上;
    2. 给内核中断处理程序注册一个回调函数,告诉内核,如果这个句柄的中断到了,就把它放到准备就绪list链表里。

    调用epoll_wait时,做了以下事情:

    观察list链表里有没有数据。有数据就返回,没有数据就sleep,等到timeout时间到后即使链表没数据也返回。而且,通常情况下即使我们要监控百万计的句柄,大多一次也只返回很少量的准备就绪句柄而已,所以,epoll_wait仅需要从内核态copy少量的句柄到用户态而已。

  • 相关阅读:
    tomcat server.xml 配置示例
    Vue学习1:实例及生命周期
    flex布局
    从输入一个URL到页面完全显示发生了什么?
    webstorm配置eslint【标记错误,修复错误】
    JavaScript实现八大内部排序算法
    es6(六):module模块(export,import)
    es6(五):class关键字(extends,super,static)
    es6(四):Symbol,Set,Map
    es6(三):es6中函数的扩展(参数默认值、rest参数、箭头函数)
  • 原文地址:https://www.cnblogs.com/pengyusong/p/5812690.html
Copyright © 2020-2023  润新知