I/O多路复用

参考:https://www.zhihu.com/question/28594409

       I/O多路复用(multiplexing)的本质是通过一种机制(系统内核缓冲I/O数据),让单个进程可以监视多个文件描述符,一旦某个描述符就绪(一般是读就绪或写就绪),能够通知程序进行相应的读写操作。

     与多线程和多进程相比,I/O 多路复用的最大优势是系统开销小,系统不需要建立新的进程或者线程,也不必维护这些线程和进程。一个线程一个进程就搞定了。

     在最开始的时候,为了实现一个服务器可以支持多个客户端连接,人们想出了fork/thread等办法,当一个连接来到的时候,就fork/thread一个进程/线程去接收并且处理请求,但越来越多的用户进行网络连接,之前的fork/thread模型就不行了。

要弄清问题,先要知道问题的出现原因 
原因:      
由于进程的执行过程是线性的(也就是顺序执行),
当我们调用低速系统I/O(read,write,accept等等),进程可能阻塞,此时进程就阻塞在这个调用上,不能执行其他操作.阻塞很正常. 接下来考虑这么一个问题:一个服务器进程和一个客户端进程通信,服务器端read(sockfd1,bud,bufsize),此时客户端进程没有发送数据,那么read(阻塞调用)将阻塞直到客户端调用write(sockfd,but,size)发来数据. 在一个客户和服务器通信时这没什么问题,当多个客户与服务器通信时,若服务器阻塞于其中一个客户sockfd1,当另一个客户的数据到达套接字sockfd2时,服务器不能处理,仍然阻塞在read(sockfd1,...)上;此时问题就出现了,不能及时处理另一个客户的       

服务,咋么办?I/O多路复用来解决!

I/O多路复用:       
继续上面的问题,有多个客户连接,sockfd1,sockfd2,sockfd3..sockfdn  同时监听这n个客户,当其中有一个发来消息时就从select的阻塞中返回,然后就调用read读取收到消息的sockfd,然后又循环回select阻塞;这样就不会因为阻塞在其中一个客户端读写上而不能处理另一个客户的消息Q。
那这样子,在读取socket1的数据时,如果其它socket有数据来,那么也要等到socket1读取完了才能继续读取其它socket的数据吧。那不是也阻塞住了吗?而且读取到的数据也要开启线程处理吧,那这和多线程IO有什么区别呢?
1.CPU本来就是线性的不论什么都需要顺序处理,并行只能是多核CPU
2.io多路复用本来就是用来解决对多个I/O监听时,一个I/O阻塞影响其他I/O的问题,跟多线程没关系.

3.跟多线程相比较,线程切换需要切换到内核进行线程切换,需要消耗时间和资源.而I/O多路复用不需要切换线/进程,效率相对较高,特别是对高并发的应用nginx就是用I/O多路复用,故而性能极佳.但多线程编程逻辑和处理上比I/O多路复用简单.而I/O多路复用处理起来较为复杂.

     不提什么I/O多路复用也能在一个线程就处理完所有的io流,用个while循环挨个处理一次不就解决了嘛?那为什么还要提出这个技术呢?原因就是刚才我们想的方法(轮询)效率太低了,资源利用率也不高。试想一下,如果某个io被设置成了阻塞io,那么其他的io将被卡死,也就浪费掉了其他的io资源。另一方面,假设所有io被设置成非阻塞,那cpu一天到晚也不用干别的事了,就在这不停的问,现在可以进行io操作了吗,直到有一个设备准备好环境才能进行io,也就是在设备准备io环境的这一段时间,cpu是没必要瞎问的,问了也没结果。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值