muduo库-网络库概括
muduo库-网络库概括
网络事件的处理模式
服务器编程中,通常有两种高效的事件处理模式:reactor模式,proactor模式。
Reactor模式
要求主线程(I/O单元)只负责监听文件描述符上是否有事件发生,有的话就立即将该事件通知工作线程(逻辑单元)。除此之外,主线程不做其他任何实质性的工作。读写数据,接受新连接,以及处理客户请求均在工作线程中完成。
使用同步I/O模型(以epoll为例)实现Reactor模式工作流程:
- 主线程往epoll内核事件表注册socket上的读就绪事件(epoll_ctl + EPOLL_CTL_ADD);
- 主线程调用epoll_wait等待socket上有数据可读;
- 当socket上有数可读时,epoll_wait通知主线程。主线程则将socket可读事件放入请求队列;
- 阻塞在请求队列上的某个工作线程被唤醒,它从socket读取数据,并处理客户请求,然后往epoll内核事件表中注册该socket上写就绪事件。
- 主线程调用epoll_wait等待socket可写;
- 当socket可写时,epoll_wait通知主线程。主线程将socket可写事件放入请求队列。
- 阻塞在请求队列上的某个工作线程被唤醒,它往socket上写入服务器处理客户请求的结果。
当然,epoll不止能监听socket上的事件,其他文件描述符都能监听。
下图是Reactor模式的工作流程示意:
Proactor模式
Proactor模式将所有I/O操作都交给主线程和内核来处理,工作线程仅负责业务逻辑。
使用异步I/O模型(以aio为例)实现Proactor模式工作流程:
- 主线程调用aio_read函数向内核注册socket上的读完成事件,并告诉内核用户读缓冲区的位置以及读操作完成时如何通知应用程序(回调函数);
- 主线程继续处理其他逻辑;
- 当socket上的数据被读入用户缓冲区后,内核将向应用程序发送一个信号,以通知应用程序数据已经可用;
- 应用程序预先定义好的信号处理函数选择一个工作线程来处理客户请求。工作线程处理完客户请求后,调用aio_write向内核注册socket上的写完成事件,并告诉内核用户写缓冲区的位置,以及写完成时如何通知应用程序(仍以信号为例);
- main线程继续处理其他逻辑;
- 当用户缓冲区的数据被写入socket之后,内核将向应用程序发送一个信号,以通知应用程序数据已经发送完毕;
- 应用程序预先定义好的信号处理函数,选择一个工作线程来做善后处理,如决定是否关闭socket;
下图是Proactor模式的工作流程示意:
muduo网络库中的Reactor模式
muduo网络库采用的是Reactor模式。服务器软件框架是one loop per thread,即一个线程一个事件循环。这个循环称为EventLoop,loop线程是指运行EventLoop::loop()的线程。这种以事件为驱动的编程模式称为事件驱动模式。
网络库是由Reactor + 线程池来完成的,线程池中每个线程都是一个Reactor模型。这种结构在处理大量并发I/O连接任务的服务器上,就很有优势。
下图是实现Reactor模式各关键类及类图关系:
参考
muduo库-网络库概括
https://gstarmin.github.io/2023/07/02/muduo库-网络库概括/