在高性能的IO设计中,有两个比较著名的模式Reactor和Proactor模式,
其中Reactor模式用于同步I/O,而Proactor运用于异步I/O操作。
Reactor模式和Proactor模式。
其实阻塞与非阻塞都可以理解为同步范畴下才有的概念,
对于异步,就不会再去分阻塞非阻塞。
对于用户进程,接到异步通知后,就直接操作进程用户空间里的数据好了。
首先来看看Reactor模式,Reactor模式应用于同步IO的场景。
我们分别以读操作和写操作为例来看看Reactor中的具体步骤。
读取操作:
应用程序注册读就绪事件和相关联的事件处理器
事件分离器等待事件的发生
当发生读就绪事件的时候,事件分离器调用第一步注册的事件处理器
事件处理器首先执行实际的读取操作,然后根据读取到的内容进行进一步的处理
写入操作类似于读取操作,只不过第一步注册的是写就绪事件。
下面我们来看看Proactor模式中读取操作和写入操作的过程。
读取操作:
应用程序初始化一个异步读取操作,然后注册相应的事件处理器,
此时事件处理器不关注读取就绪事件,而是关注读取完成事件,
这是区别于Reactor的关键。
事件分离器等待读取操作完成事件
在事件分离器等待读取操作完成的时候,操作系统调用内核线程完成读取操作
异步IO都是操作系统负责将数据读写到应用传递进来的缓冲区供应用程序操作,
操作系统扮演了重要角色),并将读取的内容放入用户传递过来的缓存区中。
这也是区别于Reactor的一点,Proactor中,应用程序需要传递缓存区。
事件分离器捕获到读取完成事件后,激活应用程序注册的事件处理器,
事件处理器直接从缓存区读取数据,而不需要进行实际的读取操作。
Proactor中写入操作和读取操作,只不过感兴趣的事件是写入完成事件。
从上面可以看出,Reactor和Proactor模式的主要区别就是真正的读取和写入操作
是由谁来完成的,Reactor中需要应用程序自己读取或者写入数据,
而Proactor模式中,应用程序不需要进行实际的读写过程,
它只需要从缓存区读取或者写入即可,
操作系统会读取缓存区或者写入缓存区到真正的IO设备。
综上所述,同步和异步是相对于应用和内核的交互方式而言的,
同步需要主动去询问,而异步的时候内核在IO事件发生的时候通知应用程序,
而阻塞和非阻塞仅仅是系统在调用系统调用的时候函数的实现方式而已。