文章来自官方文档的部分翻译:http://www.wangafu.net/~nickm/libevent-book/

通过这部分的了解,基本上可以使用libevent的常用功能了。有时间建议直接看官方文档。

一、简介

  1、Libevent组成

1)evutil:抽象各个平台上的网络实现。

2)event and event_base:libevent的核心部分,实现了异步的时间回调机制。可用于监听何时socket可读写,与超时,检测系统信号。

3)bufferevent:libevent事件核心的一种封装,以实现更简便的使用。该模块允许应用程序访问缓存起来的读写事件,以代替socket准备好时马上通知的方式。

4)evbuffer:实现bufferevent中的基本缓存功能,提供一些有效与简便的访问。

二、Setup the Libevent library

1、指定日志输出,可以通过event_set_log_callback指定日志输出(注意指定的日志输出函数中不应该调用任何libevent中的函数,否则将出现不确定的问题)。

2、处理致命错误,可以通过event_set_log_callback指定当发生不可恢复错误时的回调函数,在该函数之后不应在调用libevent中的函数。

3、内存管理,可以通过 event_set_mem_functions 指定内存分配函数

4、多线程与锁,当在多线程环境下使用libevent时,需要告知libevent使用哪种锁版本的函数,目前支持pthread与windows锁

event_set_mem_functions、evthread_use_pthreads

5、Debug锁的异常使用,evthread_enable_lock_debugging

6、Debug event的异常使用,event_enable_debug_mode

7、检测libevent版本信息

8、释放所有的全局对象libevent_global_shutdown

三、获取一个event_base对象

1、在开始libevent之前需要有event_base对象,event_base对象可以持有多个的event对象,并且可以轮询以获取那个事件已经就绪。

2、创建默认配置的event_base:event_base_new

3、创建可配置的event_base:event_config_new、event_base_new_with_config、event_config_free

4、检查event_base后端的方法:event_get_supported_method

5、释放event_base:event_base_free,注意其持有的event不对释放

6、设置event_base支持event的优先级:event_base_priority_init

7、调用系统的fork后需要reinitevent_base:event_base_reinit

四、启动事件循环

  1、运行循环,可以对已经注册了事件的event_base进行事件等待,并得到通知。  

#define EVLOOP_ONCE             0x01
#define EVLOOP_NONBLOCK 0x02
#define EVLOOP_NO_EXIT_ON_EMPTY 0x04
int event_base_loop(struct event_base *base, int flags);

  默认情况下,event_base_loop将循环执行直到其中没有注册任何事件为止。当检测到事件被触发时,该事件被标记为active,并且在循环的后面调用相应的处理函数。EVLOOP_ONCE用于指定执行一次,loop将等待事件触发,待这些触发的事件处理完成后loop退出。EVLOOP_NONBLOCK立即检查是否有事件触发,若有则处理,然后返回。EVLOOP_NO_EXIT_ON_EMPTY即使event_base中没有注册的事件也不退出,直到调用了event_base_loopbreak函数。

  简化函数evebt_base_dispatch,循环将执行直到没有事件被注册,或者调用了event_base_loopbreak或者event_base_loopexit。

2、重新检查事件

  有时在事件的回调函数中,希望event_base马上检查新的事件而不是继续处理后面已触发的事件函数,可以调用event_base_loopcontinue函数。

3、获取libevent内部时间戳:Event_base_gettimeofday_cached、event_base_update_cache_time

4、到处event_base结构内容:Event_base_dump_events

5、遍历event_base中的所有事件:event_base_foreach_event

五、处理事件

1、事件生命周期:

初始化的:创建event后并且将其关联到某个event_base;

未决的:当调用了add函数后,该事件变成未决的(即处于等待状态)

激活的:关联的等待触发时,变成激活状态,随后对应的回调函数被调用。

若事件的属性为persistent,则激活后该事件再次变成未决,否则在回调函数返回时结束。

可以通过delete来删除未决事件,或者通过add将初始转换成未决状态

2、创建事件

#define EV_TIMEOUT      0x01
#define EV_READ 0x02
#define EV_WRITE 0x04
#define EV_SIGNAL 0x08
#define EV_PERSIST 0x10
#define EV_ET 0x20
typedef void (*event_callback_fn)(evutil_socket_t, short, void *);
struct event *event_new(struct event_base *base, evutil_socket_t fd,short what, event_callback_fn cb,void *arg);
void event_free(struct event *event);

事件创建之初为non-pending,只有调用了event_add之后才变成pending。

使用示例:

#include <event2/event.h>j 

void cb_func(evutil_socket_t fd, short what, void *arg)
{
const char *data = arg;
printf("Got an event on socket %d:%s%s%s%s [%s]",
(int) fd,
(what&EV_TIMEOUT) ? " timeout" : "",
(what&EV_READ) ? " read" : "",
(what&EV_WRITE) ? " write" : "",
(what&EV_SIGNAL) ? " signal" : "",
data);
} void main_loop(evutil_socket_t fd1, evutil_socket_t fd2)
{
struct event *ev1, *ev2;
struct timeval five_seconds = {,};
struct event_base *base = event_base_new();
ev1 = event_new(base, fd1, EV_TIMEOUT|EV_READ|EV_PERSIST, cb_func,(char*)"Reading event");
ev2 = event_new(base, fd2, EV_WRITE|EV_PERSIST, cb_func, (char*)"Writing event");
event_add(ev1, &five_seconds);
event_add(ev2, NULL);
event_base_dispatch(base);
}

事件类型:

EV_TIMEOUT:指定超时事件,在创建事件的时候timeout事件被忽略,超时事件在event_add函数中指定。

EV_READ:指定可读事件

EV_WRITE:指定可写事件

EV_SIGNAL:指定信号事件

EV_PERSISTENT:指定事件为永久的(即触发后会再次进入等待)

EV_ET:指定读写事件

3、创建自己为回调函数参数的事件:event_self_cbarg

ev = event_new(base, -, EV_PERSIST, cb_func, event_self_cbarg());

该函数对如下函数event_new(), evtimer_new(), evsignal_new(), event_assign(), evtimer_assign(), and evsignal_assign().同样有效。

4、超时事件

为了方便使用,libevent提供了以evtime_开头的宏定义如下:

#define evtimer_new(base, callback, arg) \
event_new((base), -, , (callback), (arg))
#define evtimer_add(ev, tv) \
event_add((ev),(tv))
#define evtimer_del(ev) \
event_del(ev)
#define evtimer_pending(ev, tv_out) \
event_pending((ev), EV_TIMEOUT, (tv_out))

5、信号事件

Libevent执行POSIX_style的信号。

#define evsignal_new(base, signum, callback, arg) \
event_new(base, signum, EV_SIGNAL|EV_PERSIST, cb, arg)
struct event *hup_event;
struct event_base *base = event_base_new(); /* call sighup_function on a HUP signal */
hup_event = evsignal_new(base, SIGHUP, sighup_function, NULL);
#define evsignal_add(ev, tv) \
event_add((ev),(tv))
#define evsignal_del(ev) \
event_del(ev)
#define evsignal_pending(ev, what, tv_out) \
event_pending((ev), (what), (tv_out))

注意:1)不要使用信号的方式来监听超时;2)信号事件只会被一个event_base捕捉,即使为多个event_base添加信号事件也只有一个event_base会得到通知。

6、非对分配的event

7、标记事件的pending与non-pending状态

int event_add(struct event *ev, const struct timeval *tv);

使用event_add将事件从non-pending状态变成pending状态。若事件已经处于pending状态,并且tv非null则更新该事件的tv事件,若tv为null则对原有状态没有任何影响(即还是保留之前的超时设置)。另外tv为等待超时毫秒数。

int event_remove_timer(struct event *ev);

使用event_del将事件状态变成pending,若已经是pending则不操作。

int event_remove_timer(struct event *ev);

使用event_remove_timer来去除事件的超时事件设置。若事件本身是一个超时事件则该函数相当于event_del函数。

8、事件属性

int event_priority_set(struct event *event, int priority);

用于设置事件的优先级,数值为从0到event_base支持优先级减一之间。

当有高优先级事件触发时,将得到先处理,然后再次检查所有事件,当没有高优先级事件触发后才能处理低优先级事件。

优先级数值越低,优先级越高。

9、检查事件状态

int event_pending(const struct event *ev, short what, struct timeval *tv_out);

返回事件监听的处于pending或active状态的flag。若tv_out非空并且社会自了EV_TIMEOUT则返回剩余的超时事件。(不是很清楚)。   

#define event_get_signal(ev) /* ... */
evutil_socket_t event_get_fd(const struct event *ev);
struct event_base *event_get_base(const struct event *ev);
short event_get_events(const struct event *ev);
event_callback_fn event_get_callback(const struct event *ev);
void *event_get_callback_arg(const struct event *ev);
int event_get_priority(const struct event *ev);
void event_get_assignment(const struct event *event,
struct event_base **base_out,
evutil_socket_t *fd_out,
short *events_out,
event_callback_fn *callback_out,
void **arg_out);

10、一次性事件

int event_base_once(struct event_base *, evutil_socket_t, short,  void (*)(evutil_socket_t, short, void *), void *, const struct timeval *);

该事件不支持EV_SIGNAL与EV_PERSISTENT属性,并且使用默认优先级,当该事件触发一次后,有libevent自动删除。

该函数创建的事件不能手动删除与激活。

11、手动激活事件

void event_active(struct event *ev, int what, short ncalls);

Libevent详细说明的更多相关文章

  1. Libevent初探

    Libevent 是一个用C语言编写的.轻量级的开源高性能网络库,主要有以下几个亮点:事件驱动( event-driven),高性能;轻量级,专注于网络,不如 ACE 那么臃肿庞大:源代码相当精炼.易 ...

  2. libevent源码分析:http-server例子

    http-server例子是libevent提供的一个简单web服务器,实现了对静态网页的处理功能. /* * gcc -g -o http-server http-server.c -levent ...

  3. 【转】libevent和基于libevent的网络编程

    转自: http://www.cnblogs.com/nearmeng/p/4043548.html 1 libevent介绍和安装 介绍 libevent是一个轻量级的基于事件驱动的高性能的开源网络 ...

  4. 【转】libevent源码分析

    libevent源码分析 转自:http://www.cnblogs.com/hustcat/archive/2010/08/31/1814022.html 这两天没事,看了一下Memcached和l ...

  5. Centos安装Memcached和(Nginx)Memcache扩展详细教程

    下载memadmin,下载地址:http://www.junopen.com/memadmin/ 并在IIS新建站点. 测试地址:http://wap.yousawang.com/mem , 1.重启 ...

  6. libevent源码深度剖析

    原文地址: http://blog.csdn.net/sparkliang/article/details/4957667 第一章 1,前言 Libevent是一个轻量级的开源高性能网络库,使用者众多 ...

  7. linux(centos 6.4)下安装php memcache服务端及其客户端(详细教程)

    前言 在搭建个人博客时,由于没有使用任何框架,纯手工code前台和后台,导致遇到许多问题,其中一个问题就是mysql连接导致的页面相应速度异常低.在查询各种途径后,只能考虑使用memcache缓存.在 ...

  8. [原]我在Windows环境下的首个Libevent测试实例

    libevent对Windows环境也有很好的支持,不过初次学习和编译libevent简单实例,总是有一些陌生感的,只有成功编译并测试了一个实例,才会有恍然大悟的感觉.下面将要讲到的一个实例是我从网上 ...

  9. libevent和基于libevent的网络编程

    1 libevent介绍和安装 介绍 libevent是一个轻量级的基于事件驱动的高性能的开源网络库,并且支持多个平台,对多个平台的I/O复用技术进行了封装,当我们编译库的代码时,编译的脚本将会根据O ...

随机推荐

  1. Python学习教程(learning Python)--2.3.4Python函数返回值

    本节讨论Python函数返回值问题. Python和C语言一样,也可以在函数结束时返回一个值.但在定义自己的Python函数时,是不需要指定返回值数据类型的,这和Python不关心变量的数据类型是一致 ...

  2. Linux学习-0626

    6.26 Linux的安装1.下载镜像包.iso,启动时设置光盘的包是安装包,就可以看到完成安装流程 安装CentOS 5.52.安装时分区,swap分区,根分区... Linux管理工具:1.Sec ...

  3. Java生成唯一的ID

    public class UIDGenerator { private static Date date = new Date(); private static StringBuilder buf ...

  4. OpenStack: OVS安装

    > OVS安装:1. Install the Open vSwitch plug-in and its dependencies:# apt-get install \neutron-plugi ...

  5. iOS学习之C语言内存管理

         一.存储区划分      按照地址从高到低的顺序:栈区,堆区,静态区,常量区,代码区    1.栈区:局部变量的存储区域     局部变量基本都在函数.循环.分支中定义     栈区的内存空 ...

  6. FPGA控制HC595

    /*****************************************************************************Copyright: 2013File na ...

  7. CentOS7下通过rpm方式安装MySQL及插入中文问题解决 [原创]

    一 CentOS下通过rpm方式安装MySQL CentOS版本:CentOS-7 MySQL版本:MySQL-5.6.22 在网上搜了一下,Linux下安装MYSQL有三种方式: 1) 通过yum命 ...

  8. Android -- Drawable与Bitmap测试

    Drawable                                                                                 以下这个是测试加载10 ...

  9. Eigen库实现简单的旋转、平移操作

    本来课程要求用GUI界面来实现Eigen的旋转.平移操作的,但是接触GUI编程时间太短,虽然要求很简单,但是做了几天还是没有完成.就把命令行下面的简单的贴一下吧. main.cpp #include ...

  10. 卷积神经网络CNN介绍:结构框架,源码理解【转】

    1. 卷积神经网络结构 卷积神经网络是一个多层的神经网络,每层都是一个变换(映射),常用卷积convention变换和pooling池化变换,每种变换都是对输入数据的一种处理,是输入特征的另一种特征表 ...