https://blog.csdn.net/wanbf123/article/details/78062802
https://juejin.im/post/6844903636422623240
https://segmentfault.com/a/1190000002715832
https://www.zhihu.com/question/26943938/answer/68773398
0. 准备知识
一般地,IO多路复用机制都依赖于一个事件多路分离器(Event Demultiplexer)以及事件处理器(Event Handler):
- 多路分离器:分离器用于将来自事件源的I/O事件分离出来,并分发到对应的事件处理器中;
- 事件处理器:包括read/write事件处理器,也就是负责处理IO的线程或者是回调函数(在异步中)。
1. Reactor模式
- 事件分离器负责等待文件描述符或socket为读写操作准备就绪,然后将就绪事件传递给对应的处理器,最后由处理器负责完成实际的读写工作,并处理对应的逻辑。
- 事件分离器负责监听socket,并分发就绪的socket给对应的处理器;
- 处理器负责读写以及逻辑处理。
1.Reactor模式结构
可以看到,Reactor模式包含以下角色:
-
Reactor:反应器,充当事件分离器的角色,实现以下功能:
1)注册和删除关注的事件句柄;
2)运行事件循环;
3)有就绪事件到来时,分发事件到之前注册的事件处理器上处理。
-
Synchronous Event Demultiplexer:同步事件多路分离器:由操作系统内核实现的一个函数(select/epoll),用于阻塞等待发生在句柄集合上的一个或多个事件;
-
Handler:关注的事件句柄
-
Event Handler:事件处理接口
-
Concrete Event HandlerA:实现应用程序所提供的特定事件处理逻辑(继承自Event Handler),例如read。
2.处理逻辑
- 将关注的事件handle注册到Reactor中
- 调用Reactor,进入无限事件循环,等待注册的事件到来
- 事件到来,select返回,Reactor将事件(连接/读/写)分发到之前注册的回调函数中处理
3.1 单Reactor单线程模型
- Reactor 负责多路分离套接字,有新连接到来触发connect 事件之后,交由Acceptor线程进行处理,有IO读写事件之后交给hanlder 处理(也就是说,Reactor负责监听事件的到来,再将事件分发到对应的Acceptor或者Handler中);
- Acceptor负责处理connect 事件;
- Handler负责处理IO读写事件和业务逻辑,其实是Reactor线程的一部分;
3.2 单Reactor多线程模型
- Reactor 负责多路分离套接字,有新连接到来触发connect 事件之后,交由Acceptor线程进行处理,有IO读写事件之后交给hanlder 处理(也就是说,Reactor负责监听事件的到来,再将事件分发到对应的Acceptor或者Handler中);
- Acceptor负责处理connect 事件;
- 相对于单Reactor单线程而言,这里的Handler采用线程池方式,来负责处理IO读写 + 业务逻辑,这样可以减小主reactor的性能开销,从而更专注的做事件分发工作了,从而提升整个应用的吞吐。
3. 多Reactor多线程模型
3. Proactor模式
- 事件分离器:负责发起异步读写操作,并将读写完成事件传递给对应处理器;
- IO操作本身由操作系统来完成。传递给操作系统的参数需要包括用户定义的数据缓冲区地址和数据大小,操作系统才能从中得到写出操作所需数据,或写入从socket读到的数据;
- 事件处理器不用再负责IO操作,而是专注于事件的逻辑处理。
1. Proactor模式结构
Proactor模式包含如下角色:
- Async Operation Processor:异步操作处理器;负责执行异步操作,一般由操作系统内核实现;
- Completion Handler:完成事件接口;一般是由回调函数组成的接口;
- Completion Handler A(B):完成事件处理逻辑;实现接口定义特定的应用处理逻辑。
- Completion Event Queue:完成事件队列;异步操作完成的结果放到队列中等待后续使用;
- Proactor主动器:
1)为应用程序进程提供事件循环;
2)从完成事件队列中取出异步操作的结果;
3)分发调用相应的后续处理逻辑。
2. Proactor处理逻辑
- 发起I/O异步操作,注册I/O完成事件处理器;
- Proactor主动器(事件分离器),启动事件循环,等待I/O操作完成事件;
- 内核并行执行实际的I/O操作,并将结果数据存入用户自定义缓冲区;
- 内核完成I/O操作,通知事件分离器,事件分离器调度对应的事件处理器;
- 事件处理器处理用户自定义缓冲区中的数据。
一个疑问:Proactor主动器是不是也负责注册关心的socket?《Linux高性能服务器编程》中的例子:
cs