Linux高性能服务器编程-游双——第十二章 高性能IO框架库Libevent

  • Linux服务器必须处理的三类时间:IO事件、信号、定时事件
  • 处理这三类事件必须考虑三个问题:
    • 统一事件源:使用IO复用系统来管理所有事件
    • 可移植性:不同操作系统有不同的IO复用方式,Solaris的dev/poll,FressBSD的kqueue,Linux的epoll。
    • 对并发编程的支持。

12.1 I/O框架库概述

  • I/O框架库以库函数的心事,封装了较为底层的调用,给应用系统提供了一组更便捷的接口。
  • 基于Reactor模式的I/O框架库包含:

    • 1. 句柄

      • 由于IO框架库需要处理IO事件、信号和定时事件被称为统一事件源,一个句柄绑定了一个事件源.
      • 对于IO事件,句柄在Linux中的具体表现是文件描述符
      • 对于信号,句柄在Linux中的具体表现是信号值
      • 当内核检测到就绪事件后,它会通过句柄来通知应用程序。
    • 事件多路分发器[EventDemultiplexer]

      • 事件的到来是随机的、异步的。
      • IO框架库会将系统支持的各种IO复用系统调用封装成统一的接口,称为事件多路分发器。
      • demultiplex方法是等待事件的核心函数,内部调用是select、poll和epoll_wait等函数。
      • register_event:从事件多路分发器添加事件
      • remove_event:从事件多路分发器删除事件
    • 事件处理器和具体事件处理器

      • 事件处理器指向事件对于的业务逻辑。
      • 通常包含一个或多个handle_event回调函数,这些函数在事件循环中被执行。
      • 用户需要继承IO框架库提供的事件处理器,来实现自己的事件处理器,也就是具体事件处理器
      • IO框架库中的事件处理器会被声明为虚函数。
      • get_handler方法:返回与该事件相关联的句柄。当事件发生时,通过句柄来通知应用程序。
    • Reactor

      • Reactor是IO框架库核心:
        • handle_events方法:执行事件循环。重复如下过程:等待事件,依次处理所有就绪事件对应的事件处理器。
        • rigister_handler:调用事件多路分发器的register_event方法来往事件多路分发器注册事件。
        • remove_handler:调用事件多路分发器的remove_event方法来删除事件多路分发器注册事件。
          在这里插入图片描述

12.2 Libevent源码分析

#include <sys/signal.h>
#include <event.h>
void signal_cb(int, short, void*);
void timeout_cb(int, short, void*);
int main(){
    //创建event_base对象,一个event_base相当于一个Reactor实例
    struct event_base* base = event_init();
    //创建具体的事件处理器,并设置他们从属的Reactor实例
    struct event* signal_event = evsignal_new(base, SIGINT, signal_cb, base);
    //把事件添加到注册事件队列,并把事件处理器对应的事件添加到时间多路分发器。
    event_add(signal_event, NULL);
    
    timeval tv = {1, 0};
    struct event* timeout_event = evtimer_new(base, timeout_cb, NULL);
    event_add(timeout_event, &tv);

    //执行事件循环
    event_base_dispatch(base);

    //释放系统资源
    event_free(timeout_event);
    event_free(signal_event);
    event_base_free(base);

    return 0;
}
void signal_cb(int fd, short event, void* argc){
    struct event_base* base = (event_base* )argc;
    struct timeval delay = {2, 0};
    printf("Caught an interrupt signal, exiting cleanly in two seconds...\n");
    event_base_loopexit(base, &delay);

}
void timeout_cb(int fd, short event, void* argc){
    printf("timeout\n");
}

函数解析:

  • 1.event_init函数:struct event_base* base = event_init();

    • 创建event_base对象,一个event_base相当于一个Reactor实例。
  • 2.evsignal_event函数、evtimer_new函数,分别用于创建信号事件处理器,定时事件处理器。

#define evsignal_new(b, x, cb, arg) event_new((b), (x), EV_SIGNAL|EV_PERSIST, (cb), (arg))
#define evtimer_new(b, cb, arg) event_new((b), -1, 0, (cb), (arg)) 

//event_new函数的定义:
struct event* event_new(struct event_base* base, evutil_socket_t fd, short events, void (*cb)(evutil_socket_t, short, void*), void* arg);
  • 对于event_new函数,其参数含义如下:

    • base:指定新创建的事件处理器的从属Reactor。
    • fd:指定与该事件处理器关联的句柄。对于IO事件处理器,fd是文件描述符;对于信号事件处理器,fd是信号值;对于定时事件处理器,要给fd传递-1。
    • events:指定事件类型
      Libevent支持的事件类型
      EV_PERSIST作用:事件被触发后,自动对这个event调用event_add函数。
    • cb:指定目标事件的回调函数
    • arg:回调函数的参数
  • 3.event_add函数:将事件处理器添加到注册事件队列。并将该事件处理器对于的事件添加到事件多路分发器。

  • 4.event_base_dispatch函数执行事件循环

  • 5.*free系列函数用于释放系统资源

  • 6. event_base_loopexit退出事件循环。int event_base_loopexit(event_base *, const timeval *)

    • event_base指定要退出的事件循环
    • timeval指定多久之后退出

12.2.2 源代码组织结构

12.2.3 event结构体

  • event结构体封装了句柄、事件类型、回调函数、以及其他必要的标志和数据
struct event {
	struct event_callback ev_evcallback;

	/* for managing timeouts */
	union {
		TAILQ_ENTRY(event) ev_next_with_common_timeout;
		int min_heap_idx;
	} ev_timeout_pos;
	evutil_socket_t ev_fd;

	struct event_base *ev_base;

	union {
		/* used for io events */
		struct {
			LIST_ENTRY (event) ev_io_next;
			struct timeval ev_timeout;
		} ev_io;

		/* used by signal events */
		struct {
			LIST_ENTRY (event) ev_signal_next;
			short ev_ncalls;
			/* Allows deletes in callback */
			short *ev_pncalls;
		} ev_signal;
	} ev_;

	short ev_events; 	//事件类型
	short ev_res;		/* result passed to event callback */
	struct timeval ev_timeout;
};

12.2.4 往注册事件队列中添加事件处理器

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值