自学内容网 自学内容网

C++ 知识要点:I/O 模型

1. 使用同步 IO 模型实现的 Reactor 模式的工作流程(以 epoll_wait 为例)

在 Reactor 模式中,主线程(也称为事件循环或分发器)负责监听和分发事件,工作线程负责处理具体的业务逻辑。以下是使用 epoll_wait 实现 Reactor 模式的工作流程,详细描述了事件的处理过程:

1. 主线程往 epoll 内核事件表中注册 socket 上的读就绪事件
  • 主线程负责初始化并配置 epoll 实例,将服务器 socket 上的读就绪事件添加到 epoll 监听的事件列表中。
2. 主线程调用 epoll_wait 等待 socket 上有数据可读
  • 主线程执行 epoll_wait 函数,该函数会阻塞等待直到监听的事件列表中有事件发生(如 socket 上有数据可读)。
3. 当 socket 上有数据可读时,epoll_wait 通知主线程
  • 一旦有 socket 上发生读就绪事件(即客户端发送了数据),epoll_wait 会返回并通知主线程。
4. 主线程将 socket 可读事件放入请求队列
  • 主线程接收到事件后,将可读事件及其相关 socket 信息放入到一个线程安全的请求队列中。
5. 睡眠在请求队列上的某个工作线程被唤醒,它从 socket 读取数据,并处理客户请求
  • 工作线程通常会采用线程池的方式实现,它们会睡眠等待请求队列中的任务。当队列中有新任务时,工作线程被唤醒,从 socket 读取数据,处理客户请求。
  • 处理完成后,工作线程会往 epoll 内核事件表中注册该 socket 上的写就绪事件,准备发送响应。
6. 主线程调用 epoll_wait 等待写就绪事件
  • 类似于步骤 2,主线程再次调用 epoll_wait 等待 socket 上有写就绪事件发生。
7. 主线程将 socket 可写事件放入请求队列
  • 当 socket 变为可写(即可以向客户端发送数据时),epoll_wait 通知主线程,主线程将写就绪事件放入请求队列。
8. 睡眠在请求队列上的某个工作线程被唤醒,它往 socket 上写入服务器处理客户请求的结果
  • 工作线程被唤醒后,从请求队列中取出写就绪事件,向 socket 写入处理结果,完成响应。

2. 如何理解阻塞非阻塞与同步异步的区别

阻塞与非阻塞
  • 关注点:程序在等待调用结果(消息,返回值)时的状态。

  • 阻塞调用

    • 在调用结果返回之前,当前线程会被挂起。
    • 调用线程只有在得到结果之后才会返回,继续执行后续代码。
  • 非阻塞调用

    • 在不能立刻得到结果之前,该调用不会阻塞当前线程。
    • 调用会立即返回,并可能通过轮询、回调等方式通知调用者最终结果。
同步与异步
  • 关注点:消息通讯机制。

  • 同步

    • 在发出一个调用时,调用者会主动等待这个调用的结果。
    • 调用只有在得到结果后才会返回,调用者才能继续执行后续操作。
    • 调用者需要显式地等待结果。
  • 异步

    • 调用在发出之后,这个调用就直接返回了,不等待结果。
    • 调用者不会立刻得到结果,而是在未来某个时间点通过状态、通知或回调函数来处理调用结果。
    • 调用者不需要等待结果即可继续执行后续操作。

总结

  • 阻塞与非阻塞主要描述的是等待调用结果时的行为。
  • 同步与异步则关注的是调用者与被调用者之间的通讯机制,特别是结果返回的方式。

原文地址:https://blog.csdn.net/weixin_45264425/article/details/142028151

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!