美文网首页
IO多路复用

IO多路复用

作者: 九楼记 | 来源:发表于2022-03-16 23:44 被阅读0次

    Unix五种IO模型,不了解的可以 => 查看这里

    [1] blocking IO - 阻塞IO
    [2] nonblocking IO - 非阻塞IO
    [3] IO multiplexing - IO多路复用
    [4] signal driven IO - 信号驱动IO
    [5] asynchronous IO - 异步IO

    select、poll、epoll本质上也都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的。

    select

    从流程上来看,使用select函数进行IO请求和同步阻塞模型没有太大的区别,甚至还多了添加监视socket,以及调用select函数的额外操作,效率更差。但是,使用select以后最大的优势是用户可以在一个线程内同时处理多个socket的IO请求。用户可以注册多个socket,然后不断地调用select读取就绪的socket,即可达到在同一个线程内同时处理多个IO请求的目的。而在同步阻塞模型中,必须通过多线程的方式才能达到这个目的。

    select的缺点

    1. 每次调用select,都需要把fd_set集合从用户态拷贝到内核态,如果fd_set集合很大时,那这个开销也很大
    2. 同时每次调用select都需要在内核遍历传递进来的所有fd_set,如果fd_set集合很大时,那这个开销也很大
    3. 为了减少数据拷贝带来的性能损坏,内核对被监控的fd_set集合大小做了限制,并且这个是通过宏控制的,大小不可改变(限制为1024)

    poll

    poll的机制与select类似,与select在本质上没有多大差别,管理多个描述符也是进行轮询,根据描述符的状态进行处理,但是poll没有最大文件描述符数量的限制。也就是说,poll只解决了上面的问题3,并没有解决问题1,2的性能开销问题。

    epoll

    epoll在Linux2.6内核正式提出,是基于事件驱动的I/O方式,相对于select来说,epoll没有描述符个数限制,使用一个文件描述符管理多个描述符,将用户关心的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的copy只需一次。

    获取事件的时候,它无须遍历整个被侦听的描述符集,只要遍历那些被内核IO事件异步唤醒而加入Ready队列的描述符集合就行了。

    epoll的水平触发和边沿触发

    LT(Level Trigger,水平触发)模式和ET(Edge Trigger,边沿触发)模式是两种文件描述符准备就绪的通知模式。

    epoll默认是水平触发

    两者的区别在哪里呢?

    水平触发:读缓冲区非空就会一直触发,写缓冲区只要不满就会一直触发写事件。
    边缘触发:读缓冲区空转非空(有新消息)的时候触发一次,写缓冲区从满到非满的时候(空出来可以写了)触发一次。

    reference

    [1] https://www.jianshu.com/p/397449cadc9a
    [2] https://www.jianshu.com/p/76ad0ee7f948
    [3] https://www.cnblogs.com/anker/p/3265058.html

    相关文章

      网友评论

          本文标题:IO多路复用

          本文链接:https://www.haomeiwen.com/subject/azdmdrtx.html