libevent事件通知库学习笔记

libevent是一个基于reactor模式的开源事件通知库,具有高性能、轻量级等优点。本文分享了对libevent 1.4源码的一些理解。

1. libevent使用实例——event-test

libevent 1.4源码提供了一些使用实例,本文通过对其中的一个实例,来分析libevent库是如何实现事件通知功能的。以下源码取自sample/event-test.c,为了便于阅读,删除了关于WIN32的代码,去掉了对返回值的错误判断。

/*
 * event-test.c
 * Compile with:
 * cc -I/usr/local/include -o event-test event-test.c -L/usr/local/lib -levent
 */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/queue.h>
#include <unistd.h>
#include <sys/time.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <event.h>

static void fifo_read(int fd, short event, void *arg)
{
	char buf[255];
	int len;
	struct event *ev = arg;

	/* Reschedule this event */
	event_add(ev, NULL);

	fprintf(stderr, "fifo_read called with fd: %d, event: %d, arg: %p\n",
		fd, event, arg);

	len = read(fd, buf, sizeof(buf) - 1);

	buf[len] = '\0';

	fprintf(stdout, "Read: %s\n", buf);
}

int main (int argc, char **argv)
{
	struct event evfifo;
	struct stat st;
	const char *fifo = "event.fifo";
	int socket;
 
	unlink (fifo);
	mkfifo (fifo, 0600);

	socket = open (fifo, O_RDWR | O_NONBLOCK, 0);

	/* Initalize the event library */
	event_init();
	
	/* Initalize one event */
	event_set(&evfifo, socket, EV_READ, fifo_read, &evfifo);
	
	/* Add it to the active events, without a timeout */
	event_add(&evfifo, NULL);

	event_dispatch();
	return (0);
}

该程序会创建一个有名管道"event.fifo",并监听来自该管道的读事件。

# step1. 执行程序
./event-test

# step2. 重新打开一个shell,向管道中写入数据
$ echo "hello libevent!" >> event.fifo

# step3. 程序监听到管道上的读事件,并打印管道收到的消息内容
fifo_read called with fd: 3, event: 2, arg: 0x7ffcb6014440
Read: hello libevent!

2. 分析

2.1 event_init

event_init用来初始化一个reactor,libevent中使用结构体event_base来描述一个reactor实例,在event_init函数中,调用event_base_new函数为reactor实例分配内存并初始化,然后用一个全局的event_base指针变量(current_base)指向这块内存。

struct event_base {
	const struct eventop *evsel;
	... ...
};

struct eventop提供了包括初始化(init)、添加事件(add)、删除事件(del)、派发事件(dispatch)等功能,libevent提供了一张全局表eventops,在eventops中,将各种具有不同实现的eventop实例用宏进行控制,然后在event_init阶段将evsel指针指向对应的eventop实例。libevent使用了小根堆来管理定时事件。

// 如下是一个典型的eventop实例,底层基于epoll实现对事件的添加、删除、派发等
const struct eventop epollops = {
	"epoll",
	epoll_init,
	epoll_add,
	epoll_del,
	epoll_dispatch,
	epoll_dealloc,
	1 // need reinit 
};

2.2 event_set

event_set函数用来初始化一个事件。libevent使用struct event来表示一个具体的事件。event_set对一个event实例进行初始化,包括设置fd、事件类型、事件处理函数及其参数。

libevent中定义的部分事件类型:

#define EV_TIMEOUT	0x01
#define EV_READ		0x02
#define EV_WRITE	0x04
#define EV_SIGNAL	0x08

2.3 event_add

event_add将事件添加到reactor中。对于定时器事件,将其添加到小根堆中。对于读写事件、信号事件,使用eventop中的add函数来添加事件,然后将事件添加到reactor中的事件队列(eventqueue)中去。

2.4 event_dispatch

通过event_dispatch启动事件循环,监听事件队列中的事件,当有事件发生时,调用eventop中的dispatch函数处理事件。

event_dispatch --> event_loop(0) --> event_base_loop(current_base, 0)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值