Reactor反应堆模式

Reactor是事件分发器,基于IO 多路复用(epoll/poll/select) + 事件回调,把IO事件、读写、异常统一监听、分发到对应处理函数,是高性能网络服务经典模型

总结来说,Reactor = IO 多路复用 + 事件分发 + 回调

1. 思路

2. 参考代码

Reactor模式实现代码

3. 附加

OneThreadOneLoop多进程方案

One Thread One Loop (OTOL)是一种设计模式,通常用于描述基于事件驱动编程(Event Driven Programming)的架构,特别是在使用异步I/O(Asynchronous I/O)框架时。这种模式强调每个线程运行一个独立的事件循环(Event Loop),从而实现高效的并发处理。

核心概念

事件循环(Event Loop):

  • 事件循环是异步编程的核心,负责监听事件(如 I/O 操作、定时器事件等)并触发相应的回调函数
  • 通常是一个单线程的执行模型,通过多路复用技术(如 epoll 、 select 或 poll )高效地管理多个 I/O 操作

单线程模型

  • 在 One Thread One Loop 模式中,每个线程运行一个独立的事件循环
  • 这种设计避免了多线程编程中的复杂同步问题,同时利用了现代操作系统高效的 I/O 多路复用机制
  • 只要把单 Reactor 写完,扩展多进程很容易
  • 每个进程管理的连接和 fd,彼此不要重复
  • 每个 Reactor,自己处理自己的 sockfd 的完整生命周期,不涉及任何 IO 穿插、乱序问题

多线程方案1

Eventfd事件驱动

如果不使用管道的话,可以使用Eventfd

  • 是一个轻量级的事件通知机制,基于文件描述符
  • 它可以与I/O多路复用机制(如epoll )结合使用
  • 内核维护一个64位的计数器, write会增加计数器, read 会减少

进程间事件通知:

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/eventfd.h>
#include <sys/wait.h>

int main() {
    // 创建一个 eventfd 文件描述符,用来发事件
    // EFD_CLOEXEC:执行新程序时自动关闭,安全规范
    int efd = eventfd(0, EFD_CLOEXEC);
    if (efd == -1) {
        perror("eventfd");
        return 1;
    }

    // fork() 创建子进程
    // 调用后,变成两个进程:父进程 + 子进程
    pid_t pid = fork();
    if (pid == -1) {
        perror("fork");
        return 1;
    }

    if (pid == 0) {
        // 这里是 【子进程】
        uint64_t value;
        // 阻塞等待:读取 eventfd,直到有人写入才会继续
        read(efd, &value, sizeof(value));
        printf("Child process received event\n");
        close(efd);
        return 0;
    } else {
        // 这里是 【父进程】
        uint64_t value = 1;
        // 向 eventfd 写入 = 发送事件
        write(efd, &value, sizeof(value));
        printf("Parent process sent event\n");
        
        wait(NULL); // 等待子进程结束
        close(efd);
        return 0;
    }
}

流程:

创建 eventfd --> fork子进程 --> 子进程阻塞在 read,等事件 --> 父进程 write,发送事件 --> 子进程收到,打印提示 --> 结束

线程间事件通知:

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/eventfd.h>
#include <pthread.h>

// 工作线程函数
void* worker_thread(void* arg) {
    int efd = *(int*)arg; // 获取 eventfd
    uint64_t value;
    
    // 阻塞等待事件
    read(efd, &value, sizeof(value));
    printf("Worker thread received event\n");
    return NULL;
}

int main() {
    // 创建 eventfd
    int efd = eventfd(0, EFD_CLOEXEC);
    if (efd == -1) {
        perror("eventfd");
        return 1;
    }

    pthread_t thread;
    // 创建工作线程
    pthread_create(&thread, NULL, worker_thread, &efd);

    // 主线程:发送事件
    uint64_t value = 1;
    write(efd, &value, sizeof(value));
    printf("Main thread sent event\n");

    // 等待工作线程结束
    pthread_join(thread, NULL);
    close(efd);
    return 0;
}

流程:

创建 eventfd --> 创建一个工作线程 --> 工作线程阻塞在 read,等事件 --> 主线程 write,发送 --> 工作线程收到,打印提示 --> 结束

Eventfd工作模式

  1. 普通模式:不设置 EFD_SEMAPHORE ,读取的时候,计数器会清空
  2. 设置EFD_SEMAPHORE :信号量模式

多线程方案2

相关推荐
Cat_Rocky2 小时前
Linux-Jenkins自动化部署PHP项目
linux·自动化·jenkins
Shadow(⊙o⊙)2 小时前
Linux内核级文件系统分析——文件系统入门内核级文章!
linux·运维·服务器·开发语言·c++
取经蜗牛10 小时前
Ubuntu 国内镜像源配置指南(多版本常用镜像地址都有)
linux·运维·ubuntu
实心儿儿11 小时前
Linux —— 线程控制(1)
linux·运维·服务器
筠筠喵呜喵12 小时前
Linux软件开发性能优化
linux·c++·性能优化
仰泳之鹅12 小时前
【物联网】使用MQTTX与OneNET云平台进行模拟MQTT协议通信
网络·物联网
Bruce_kaizy12 小时前
c++ linux环境编程——文件io介绍以及open 、write 、read 三剑客深度详解
linux·服务器·c++·ubuntu·操作系统·文件io
亦良Cool12 小时前
VMware虚拟机ubuntu瘦身,解决虚拟机越用越大
linux·运维·ubuntu
星辰&与海14 小时前
KVM + QEMU虚拟化方案
linux·运维