IO模型:2、多路复用模型

引用

        一篇干货博客:

        select的原理和用法:FD_SET的使用

写在前面

        在阻塞模型中,线程发起IO会阻塞直到IO完成才返回。在单线程无并发的工作中这并无不妥,但如果是一套需要高并发的逻辑,例如网络服务器,此时这种模型显然不合理。

        从本文开始介绍经典常用的非阻塞IO模型,各种模型如何调配调度对于IO调用的合理安排能大大提高系统的效率、提升吞吐率降低系统资源调度的额外开销。

模型阐释

        从 IO模型:2、阻塞模型 结合 IO模型:1、IO模型初识 知识,我们可以知道accept函数其实是从已连接队列中取出一个就绪的套接字进行IO数据拷贝,也就意味着,在取出这个套接字时队列中依然可能存在0-N个已就绪的套接字,而这些套接字却只能排队依次等待其前面的IO完成,这样的等待时间无疑是漫长的

        而非阻塞模型解决了上述问题,但是所有请求的线程不断地轮询内核的IO状态,这使得CPU进入了忙等,大量的CPU运行时机用于轮序IO是否就绪

        因此自然而然我们会想到我们可以在非阻塞模型中派一个线程进行轮询当存在一个或多个就绪IO时,一次性将所有就绪的 fd(File Descriptor) 取出,将就绪的fd派发对应线程让其执行逻辑,这样就减少了大量的IO轮询开销。

特点

        能同时处理更多的连接,而不是对于单个连接能够处理的更快。非阻塞IO模型(NIO)中,需要 N (N>=1)次轮询系统调用,然而借助 select 的IO多路复用模型,只需要发起一次询问就够了,大大优化了性能。

        select函数返回后,是通过 遍历fdset ,找到就绪的描述符 fd 。(仅知道有I/O事件发生,却不知是哪几个流,所以 遍历所有流)。select参数的fd_set结构长度有限,一般是1024。

        因为 存在连接数限制,所以后来又提出了 poll。与select相比, poll解决了 连接数限制问题。但是呢,select和poll一样,还是需要通过遍历文件描述符来获取已经就绪的 socket 。如果同时连接的大量客户端,在一时刻可能只有极少处于就绪状态,伴随着监视的描述符数量的增长, 效率也会线性下降

使用epool的多路复用

        为了解决 select/poll 存在的问题,多路复用模型 epoll 诞生,它采用事件驱动来实现。

        epoll先通过 epoll_ctl 来注册一个 fd (文件描述符),一旦基于某个 fd 就绪时,内核会采用回调机制,使当前fd处于有信号状态 ,当进程调用 epoll_wait 时便得到通知。这样省去遍历文件描述符 的操作提升了效率,而是采用 监听事件回调的机制。这就是epoll的亮点。

select、poll、epoll的区别

轮询函数同步数据结构获取就绪fd方法复杂度最大连接fd数据拷贝
select数组遍历O(n)1024内核拷贝到用户空间
pool链表遍历O(n)无限制内核拷贝到用户空间
epool红黑树和链表事件回调O(1)无限制使用内存映射(mmap)

         epoll明显优化了IO的执行效率,但在线程调用 epoll_wait 时,未就绪的线程处于阻塞状态,其实大部分线程都处于阻塞状态。

总结

        在本篇中涉及的模型优化了 IO就绪前队列等待的问题,加快了响应速度,并且减少了IO轮询的CPU负担,之后又进一步降低了程序调用IO的成本。

        该模型针对获取IO就绪状态的流程几乎达到最优。

        但同样存在不足

                1、存在多少IO请求就对应多少条线程,并发数达到一定数量后反而降低效率。

                2、这些线程大部分时间依然在等待对应的IO转为就绪。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值