当前位置: 首页 > news >正文

存储系统02——Libevent事件循环

存储系统02——Libevent

  • 多路复用(Multiplexing)与多路分解(Demultiplexing)
  • I/O多路复用(I/O Multiplexing)
    • 阻塞I/O
    • I/O多路复用
  • Reactor反应堆模式
  • Libevent库
    • Libevent事件实例(HTTP 服务)

多路复用(Multiplexing)与多路分解(Demultiplexing)

多路复用(Multiplexing):将多个流合并到一个共享资源(某个线程)中,以便节省系统资源;
多路分解(Demultiplexing):将合并后的流分离成多个原始流,便于后续同步地、有序地处理同时接收的多个请求;

I/O多路复用(I/O Multiplexing)

Linux系统将磁盘、网络等均描述为文件(Everything is File),所以任何形式的I/O都可以称为文件IO;
同时把可以进行I/O操作的内核对象(文件描述符Fd、网络套接字Socket)称为I/O流;

write
read
A
文件
B

阻塞I/O

当有多个进程尝试进行对同一个文件进行I/O操作时,在阻塞I/O方法中,由于每个请求都会阻塞进程/线程,因此需要为每个请求分配独立的进程或线程来处理。在高并发场景下,这种模型会消耗大量系统资源(如内存和上下文切换开销),导致性能瓶颈。

write
write
write
read
A
文件
B
C
D

I/O多路复用

多路:多个I/O请求
复用:通过一个线程监听多个I/O流的就绪状态,而不需要每个I/O流创建单独的线程,从而节省系统资源,多路复用主要有三种:select、poll、epoll;

I/O多路复用本质上还是一种同步I/O,即程序自己执行自己的读写操作,这个过程是阻塞的;而异步I/O则无需自己负责进行读写,进程发起I/O操作后不会被阻塞,内核会负责完成整个 I/O 操作并在完成后通知进程。

Reactor反应堆模式

为了实现事件驱动中将一个或多个客户的服务请求分离(Demultiplexing)和调度(dispatch)给程序,通常采取Reactor反应堆模式;

Reactor反应堆模式是一种用于处理并发 I/O 操作的设计模式,广泛应用于高性能服务器和网络编程中;它通过一个事件循环(Event Loop)和一组事件处理器(Handlers)来高效地处理多个并发事件;Reactor 模式的核心思想是将事件的监听分发和处理分离,从而实现高效的并发处理

工作过程为:一个负责监听和分发事件的事件循环(Event Loop)持续检查事件源(如文件描述符)的状态变化,使用同步事件分离器(Event Demultiplexer)将检测到的事件分发给对应的事件处理器(Event_handler),事件处理器执行完成后,控制权返回到事件循环,继续监听新的事件,重复上述过程。
在这里插入图片描述
Reactor优势:

  1. 通过事件循环和事件处理器的分离,Reactor 模式能够高效地处理多个并发事件,避免了传统阻塞 I/O 模式下的线程阻塞问题;
  2. 事件循环通常运行在单个线程中,减少了线程上下文切换的开销;
  3. 可以通过增加事件处理器来处理更多类型的事件,而无需修改事件循环的逻辑。

Libevent库

Libevent 是一个用 C 语言编写的开源高性能事件通知库,主要设计用于处理网络 I/O 事件、定时事件和信号事件;基于事件循环(Event Loop),当事件(如文件描述符可读、可写、超时等)发生时,自动调用注册的回调函数。

Libevent事件实例(HTTP 服务)

使用 libevent 需要分配一个event_base结构体,每个event_base结构体持有一个事件集合,可以检测有哪些事件发生;event_base可以指定一个I/O多路复用方法(以epoll为例)

  1. 使用event_base_new()函数分配并且返回一个新的具有默认设置的event_base结构体;使用完event_base之后,使用 event_base_free()进行释放。
event_base *base = event_base_new(); // 实例化一个 event_base
.......
if (base)event_base_free(base); // 释放指定 event_base
  1. 使用 event_new() 接口注册事件,HTTP服务器可以使用evhttp_new()接口注册evhttp上下文,返回一个被用于监测的文件httpd;使用evhttp_free(httpd)释放事件。
evhttp *httpd = evhttp_new(base); // 创建evhttp上下文
.......
if (httpd)evhttp_free(httpd); // 释放指定 evhttp
  1. 创建事件完成后,使用evhttp_set_gencb()接口向事件设定回调函数GenHandler,该回调函数通过读取evhttp中不同的URL请求(Download、Upload、ListShow)并执行对应的操作。
evhttp_set_gencb(httpd, GenHandler, NULL); // 设定回调函数
  1. 当event_base注册了一些事件之后,就需要让 libevent 等待事件并且通知事件的发生;执行循环时,函数重复地检查是否有任何已经注册的事件被触发
event_base_dispatch(base); // 启动事件循环

以上就完成了基于libevent的一个http服务,完整代码如下:

// 初始化和启动一个基于 libevent 和 evhttp 的 HTTP 服务
bool RunModule()
{// 初始化环境event_base *base = event_base_new();// 设置监听的端口和地址sockaddr_in sin;memset(&sin, 0, sizeof(sin));sin.sin_family = AF_INET;sin.sin_port = htons(server_port_);// http 服务器,创建evhttp上下文evhttp *httpd = evhttp_new(base);// 绑定端口和ipevhttp_bind_socket(httpd, "0.0.0.0", server_port_) // 将 HTTP 服务器绑定到指定的 IP 地址和端口// 设定回调函数evhttp_set_gencb(httpd, GenHandler, NULL);// 使用 event_base_dispatch 启动事件循环,开始处理事件event_base_dispatch(base)// 释放释放事件if (base) event_base_free(base);if (httpd) evhttp_free(httpd);return true;
}
http://www.xdnf.cn/news/534061.html

相关文章:

  • Interrupt 2025 大会回顾:关于LangChain 的 AI Agent会议内容总结
  • anythingLLM支持本地大模型嵌入知识库后进行api调用
  • Linux 系统异常触发后自动重启配置指南
  • 深入解析PyTorch中MultiheadAttention的参数key_padding_mask与attn_mask
  • 【AI时代】Java程序员大模型应用开发详细教程(上)
  • ALTER AGGREGATE使用场景
  • Pod 节点数量
  • 【Game】Powerful——Punch and Kick(12)
  • 阿里世界偏好模型:WorldPM-72B论文速读
  • LangChain框架核心技术:从链式工作流到结构化输出的全栈指南
  • Spring的后置处理器是干什么用的?扩展点又是什么?
  • 数据结构学习笔记—初识数据结构
  • 用Caffeine和自定义注解+AOP优雅实现本地防抖接口限流
  • 玉米籽粒发育
  • spring boot 注解 @bean
  • 打卡30天
  • 【IDEA】删除/替换文件中所有包含某个字符串的行
  • ROS2简介
  • 关于ECMAScript的相关知识点!
  • 适合学人工智能的专业有哪些?
  • 【算法】滑动窗口动态查找不含重复字符的最长子串
  • 同一颗太阳:Australia、Austria、Arab、Africa、Augustus、August、Aurora、Athena
  • input组件使用type=“number“的时候,光标自动跳到首位
  • 深度学习基础——神经网络优化算法
  • 免费私有化部署! PawSQL社区版,超越EverSQL的企业级SQL优化工具面向个人开发者开放使用了
  • 游戏盾的功有哪些?
  • AGI大模型(27):LangChain向量存储
  • react事件绑定的方法
  • 桌面麒麟系统下的GMAC调试日志
  • HTTPS、SSL证书是啥?网站“安全小锁”的入门科普