多路复用及同步、异步和阻塞、非阻塞

来源:互联网 发布:黑莓怎么改网络标识 编辑:程序博客网 时间:2024/06/07 17:13

今天查询了很多关于多路复用之类的资料,特浅陋整理一下,有助于记忆。

其实这些概念都仅仅是实践中的概念而已,没必要理论是的加以定义,但也要是自己弄清楚,才能明确这些术语的应用场景。

1、同步和异步I/O

弄清这些概念,先从Reactor和Proactor这两个模式说起,网上的介绍很多,自己也没有什么时间仔细的分析、学习具体的模式内容和代码,这里只是讲讲他们的共同点和不同点。

共同点:依赖于Event Demultiplexer,I/O事件发生后都需要callback handler;

不同点:Reactor callback handler说明I/O就绪,可以进行相关操作(read/write),由相关处理器来完成实际操作,这就是同步I/O

                 Proactor callback handler说明I/O已经完成相关操作,处理器不需要再操心I/O的read或write了,这就是异步I/O

2、明确了同步和异步I/O如何划分之后,然后要搞清楚什么是 多路复用,这里又涉及到阻塞和非阻塞等。

(1)同步和异步是针对应用程序和内核的交互而言的,同步指的是Application(用户应用程序/用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪,而异步是指Application触发IO操作以后便开始做自己的事情,而当IO操作已经完成的时候会得到IO完成的通知。

(2)阻塞和非阻塞是针对于进程在访问数据的时候,根据IO操作的就绪状态来采取的不同方式,说白了是一种读取或者写入操作函数的实现方式,阻塞方式下读取或者写入函数将一直等待,而非阻塞方式下,读取或者写入函数会立即返回一个状态值。

阻塞式

非阻塞式


(3)多路复用是同步非阻塞I/O,即Synchronous I/O Multiplexing,它是利用单独的线程(内核级)统一监测所有Socket,一旦某个Socket有了I/O数据,则启动相应的Application处理,在select和poll中利用轮询socket句柄的方式来实现监测socket中是否有I/O数据到达,这种方式有开销,epoll等则改进了这种方式,利用底层notify机制,即Reactor方式来监测,Java NIO也是采用这种机制。这里需要注意,其实多路复用还是有阻塞的(这个阻塞并非以上定义的阻塞,这里指Socket无I/O数据时还是被wait,此外当使用select函数copy I/O数据入Application Buffer时,Application还是被阻塞的),不影响它属于非阻塞,轮询始终会立即有返回值,而传统的同步阻塞I/O(Application被阻塞,直到I/O操作完成才有返回值方能继续执行其他操作)为了解决并发访问问题,不能因为处理一个客户端的请求,使其它客户端长时间等候,而去为每一个客户端创建一个Thread,而大部分时间这些Thread都需要等待I/O数据而“休息中”,造成资源浪费,也增加了CPU负担,多路复用很好的解决了这个问题。

(4)以下引自http://blog.csdn.net/shallwake/article/details/5265287

I/O multiplexing (select and poll) 
最常见的I/O复用模型,select。(注:为什么没有轮询呢?struct timeval *timeout是select的超时时间,这个参数至关重要,它可以使select处于三种状态,第一,若将NULL以形参传入,即不传入时间结构,就是将select置于阻塞状态,一定等到监视文件描述符集合中某个文件描述符发生变化为止;第二,若将时间值设为0秒0毫秒,就变成一个纯粹的非阻塞函数,不管文件描述符是否有变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值;第三,timeout的值大于0,这就是等待的超时时间,即select在timeout时间内阻塞,超时时间之内有事件到来就返回了,否则在超时后不管怎样一定返回,返回值同上述。)

signal driven I/O (SIGIO) 
只有UNIX系统支持,感兴趣的课查阅相关资料

asynchronous I/O (the POSIX aio_functions) 
很少有*nix系统支持,windows的IOCP则是此模型

下面是以上五种模型的比较



原创粉丝点击