libevent 源码学习二 —— reactor 模式

1. 简介:Reactor : 反应堆模型, 一种事件驱动方式。

2. 优点

a 响应快,不必为单个同步时间所阻塞。(Reactor 本身是同步的)

b 编程相对简单,可以最大程度的避免复杂的多线程和同步问题,避免了多线程/进程的切换开销

c 可扩展性, 可以方便的通过增加Reactor实例个数来充分利用CPU资源

d 可复用性, reactor框架本身与具体事件处理逻辑无关,具有高可复用性

3. 框架

a 事件源:Linux上是文件描述符, windows上是Socket或者Handle。统称为 句柄集;程序在指定的句柄上注册关心的事件,比如 I/O 事件。

b 事件多路分发机制 :由操作系统提供的多路复用机制, select 和 epoll。在libevent中,使用了结构体eventop进行封装,以同意的接口来支持这些I/O多路复用机制。

c 反应器:Reactor 是事件管理的接口,对应到libevent中就是 event_base 结构体
一个典型的Reactor声明:
class Reactor{
public:
int register_handler(Event_Handler *pHandler, int event);

int remove_handler(Event_Handler *pHandler, int event);

void handler_events(timeval *ptv);

// ...
};

d 事件处理程序:提供了一组接口,每个接口对应了一种类型的事件,供Reactor在相应的事件发生时调用,执行对应的事件处理。通常会绑定一个有效的句柄。对应到libevent中就是event结构体
两个典型的事件处理程序

class reactor{
public:
virtual void handle_read() = 0;
virtual void handle_write() = 0;
virtual void handle_timeout() = 0;
virtual void handle_close() = 0;
virtual HANDLE get_handle() = 0;
// ...

};

class Event_Handler{
public:
// events may be read/write/timeout/close.etc
virtual void handle_events(int events) = 0;
virtual HANDLE get_handle() = 0;
//...
};

4 Rerctor 事件处理流程

a 主线程往 epoll 内核事件表中注册 socket 上的读就绪事件

b 主线程调用 epoll_wait 等待 socket 上的读就绪事件

c 当 socket 上有数据可读时,epoll_wait 通知主线程。主线程则将 socket 可读事件放入请求队列

d 睡眠在请求队列中的某个工作进被唤醒,它从socket读取数据,并处理客户请求,然后往 epoll 内核事件表中注册该 socket 上的写就绪事件

e 主线程调用 epoll_wait 等待 socket 可写

f 当socket 可写时,epoll_wait 通知主线程,主线程则将 socket 可写事件放入请求队列

g 睡眠在请求队列中的某个工作线程被唤醒,它往 socket 中写入服务器客户请求的结果

原文地址:https://www.cnblogs.com/sanerer/p/10704773.html

时间: 2024-08-27 02:56:19

libevent 源码学习二 —— reactor 模式的相关文章

Dubbo源码学习(二)

@Adaptive注解 在上一篇ExtensionLoader的博客中记录了,有两种扩展点,一种是普通的扩展实现,另一种就是自适应的扩展点,即@Adaptive注解的实现类. @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) public @interface Adaptive { String[] value() default {}; } @Adapt

python 协程库gevent学习--gevent源码学习(二)

在进行gevent源码学习一分析之后,我还对两个比较核心的问题抱有疑问: 1. gevent.Greenlet.join()以及他的list版本joinall()的原理和使用. 2. 关于在使用monkey_patchall()之后隐式切换的问题. 下面我将继续通过分析源码及其行为来加以理解和掌握. 1. 关于gevent.Greenlet.join()(以下简称join)先来看一个例子: import gevent def xixihaha(msg): print(msg) gevent.sl

[spring源码学习]二、IOC源码——配置文件读取

一.环境准备 对于学习源码来讲,拿到一大堆的代码,脑袋里肯定是嗡嗡的,所以从代码实例进行跟踪调试未尝不是一种好的办法,此处,我们准备了一个小例子: package com.zjl; public class Person { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public void sayHello

ejabberd源码学习——方法注册模式

什么叫方法注册模式? 简言之,就是在方法被调用之前,先将方法名与调用此方法的触发条件的关键字建立一种映射关系,当指定的触发条件成立时,相应的方法则将会被调用.称之为方法注册模式,实乃一家之言,关键囿于人懒,从而书读得少,代码写得寡.闲话休谈,待入正题. 在学习ejabberd源码(版本14.07)中,发现通过配置表就可以使得某些模块启用或不启用,相当灵活,其主要是通过利用第一段所说的方法注册模式来实现.可以发现很多mod_xxx模块的start方法中都有下面两个方法的调用: gen_iq_han

muduo库源码剖析(一) reactor模式

一. Reactor模式简介Reactor释义"反应堆",是一种事件驱动机制.和普通函数调用的不同之处在于:应用程序不是主动的调用某个API完成处理,而是恰恰相反,Reactor逆置了事件处理流程,应用程序需要提供相应的接口并注册到Reactor上,如果相应的时间发生,Reactor将主动调用应用程序注册的接口,这些接口又称为"回调函数". 二. moduo库Reactor模式的实现 muduo主要通过3个类来实现Reactor模式:EventLoop,Channe

Thrift源码学习二——Server层

Thrift 提供了如图五种模式:TSimpleServer.TNonblockingServer.THsHaServer.TThreadPoolServer.TThreadSelectorServer ?? TSimpleServer.TThreadPoolServer 属于阻塞模型 TNonblockingServer.THsHaServer.TThreadedSelectorServer 属于非阻塞模型 TServer TServer 为抽象类 public static class Ar

Bottle 框架源码学习 二

上一篇简单分析了route的基本用法 本篇分析一下run函数的运行原理 def run(app=None, server='wsgiref', host='127.0.0.1', port=8080,         interval=1, reloader=False, quiet=False, plugins=None,         debug=None, **kargs):          if NORUN: return     if reloader and not os.env

Nmap 源码学习二 整体架构

目录功能: docs :相关文档 libdnet-stripped :开源网络接口库 liblinear:开源大型线性分类库 liblua:开源Lua脚本语言库 libnetutil:基本的网络函数 libpcap:开源抓包库 libpcre:开源正则表达式库 macosx:xcode项目文件 mswin32:vs项目文件 nbase:Nmap封装的基础使用函数库 ncat:netcat网络工具,由Nmap实现 ndiff:比较Nmap扫描结果的实用命令 nmap-update:负责Nmap更新

jQuery源码学习(二)

回调对象Callbacks 回调对象Callbacks就是用来管理回调函数队列的. 参数说明 它提供几个便捷的处理参数 - once: 确保这个回调列表只执行一次 - memory: 保持以前的值,将添加到这个列表的后面的最新的值立即执行调用任何回调 - unique: 确保一次只能添加一个回调(所以在列表中没有重复的回调). - stopOnFalse: 当一个回调返回false 时中断调用 once和stopOnFalse作用于fire memory和unique作用于add once在源码