IO多路复用(新)

本文探讨了从阻塞IO和非阻塞IO的效率问题,引出IO多路复用的概念,重点介绍了select、poll和epoll三种模式,以及它们的优缺点,特别是epoll的事件通知机制及其与LT和ET模式的选择。最后提到在Web服务中的应用和惊群问题的解决策略。
摘要由CSDN通过智能技术生成

1.前景回顾

        无论是阻塞IO还是非阻塞IO,用户应用在一阶段都需要调用recvfrom来获取数据,差别在于无数据时的处理方案:

  • 如果调用recvfrom时,恰好内核没有数据,那么阻塞IO会使用户进程阻塞,非阻塞IO使CPU进行空转,都不能充分发挥CPU的作用。

  • 如果调用recvfrom时,恰好内核有数据,则将内核数据读取到用户区处理即可。

        而且在多个读取请求单线程处理的情况下,只能依次处理一个个请求,一旦正在处理的请求的数据没有准备好,那么全体阻塞,性能很差。

        可以利用多线程来改进,但也要考虑上下文切换的时间成本。能不能利用一个线程同时监听这多个读请求,一旦哪个请求所需要的数据在内核中准备就绪了,我们就去读取数据。

        那么用户进程如何知道内核中的数据是否准备好了呢?

2.FD(文件描述符)

        文件描述符:简称FD,是一个从0开始递增的无符号整数,用来关联Linux中的一个文件,也包括Socket。IO多路复用是利用一个线程来同时监听多个FD,并在某个FD可读、可写时得到通知,从而避免无效的等待,充分利用CPU资源。

3.IO多路复用概述

监听FD的方式又有多种实现,监听都是在内核实现的,常见的有:select、poll和epoll模式。

它们之间的差异在于:

  • select和poll只会通知用户进程有几个FD就绪,但不确定具体是哪个FD,还是需要用户进程逐个遍历FD来确认。

  • epoll则会在通知用户进程FD就绪的同时,把已经就绪的FD写入用户空间。

4.IO多路复用——select

        select是Linux中最早的I/O多路复用实现方案,采用数组实现:

4.1select方案的缺点:

  • 用户进程无法得知是哪个fd就绪,需要遍历整个fd_set。

  • fd_set监听的fd数量不超过1024。

  • 需要来回将整个fd_set在用户和内核之间互相拷贝。

5.IO多路复用——poll

        poll模式对select模式做了简单的改进,但性能提升不明显,也是只会通知用户进程有几个fd准备就绪了。区别就是poll模式在内核中采用链表存储,理论上无上限,但是监听的FD越多,每次遍历耗时也会越长,性能反倒会下降。

6.IO多路复用——epoll

        epoll模式中内核采用的是call back事件回调,利用红黑树保存要监听的FD,而且每个FD只需要初始时添加一次到红黑树,等到红黑树中的FD就绪了,会自动触发事件,把对应的FD加入到一个就绪列表(list_head)中,当用户进程要检查内核就绪列表时(调用epoll_wait),如果列表不为空则返回已就绪的FD的数量,并把链表中的值拷贝到用户空间的events数组中,用户空间根据数组中的值就能直接定位可以读取的FD,然后去读取数据即可。

7.IO多路复用——事件通知机制

        对于用户进程来说,我们调用epoll_wait函数查看就绪列表就能得到fd的通知。其事件通知的模式有两种:LT和ET。一个例子:

 

LT:当就绪队列中有可读的FD时,调一次通知一次,这样会重复通知多次,直至数据全部读取完成。(默认)

ET:当就绪队列中有可读的FD时,只会通知一次,然后直接删除,不管用户是否一次能够读完。

        根据上面的分析,我们发现那肯定是LT好,但是LT会存在惊群问题,比如我们有多个进程同时在关心这一个socket的读取数据,其实实际读取操作一两个进程就能完成,但是你每次一调用epoll_wait函数,都会惊动所有进程去读,所以就没有必要。

8.IO多路复用——Web服务流程

 

 

  • 22
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值