首先给出官方文档吧: http://libevent.org ,首页有个Programming with Libevent,里面是一节一节的介绍libevent,但是感觉信息量太大了,而且还是英文的-。-(当然,如果想好好用libevent,看看还是很有必要的),还有个Reference,大致就是对各个版本的libevent使用doxgen生成的文档,用来查函数原型和基本用法什么的。

下面的来着文档:http://www.wangafu.net/~nickm/libevent-book

Libevent is divided into the following components:

evutil

Generic functionality to abstract out the differences between different platforms' networking implementations.

event and event_base

This is the heart of Libevent. It provides an abstract API to the various platform-specific, event-based nonblocking IO backends. It can let you know when sockets are ready to read or write, do basic timeout functionality, and detect OS signals.

bufferevent

These functions provide a more convenient wrapper around Libevent’s event-based core. They let your application request buffered reads and writes, and rather than informing you when sockets are ready to do, they let you know when IO has actually occurred.

The bufferevent interface also has multiple backends, so that
it can take advantage of systems that provide faster ways to do
nonblocking IO, such as the Windows IOCP API.
evbuffer

This module implements the buffers underlying bufferevents, and provides functions for efficient and/or convenient access.

evhttp

A simple HTTP client/server implementation.

evdns

A simple DNS client/server implementation.

evrpc

A simple RPC implementation.

Setting up the Libevent library

Libevent has a few global settings that are shared across the entire process. These affect the entire library.

You must make any changes to these settings before you call any other part of the Libevent library. If you don’t, Libevent could wind up in an inconsistent state.

Memory management

By default, Libevent uses the C library’s memory management functions to allocate memory from the heap. You can have Libevent use another memory manager by providing your own replacements for malloc, realloc, and free. You might want to do this if you have a more efficient allocator that you want Libevent to use, or if you have an instrumented allocator that you want Libevent to use in order to look for memory leaks.

;或者希望libevent 使用一个工具分配器,以便检查内存泄漏时,可能需要这
样做。

Interface
void event_set_mem_functions(void *(*malloc_fn)(size_t sz),
void *(*realloc_fn)(void *ptr, size_t sz),
void (*free_fn)(void *ptr));

Here’s a simple example that replaces Libevent’s allocation functions with variants that count the total number of bytes that are allocated. In reality, you’d probably want to add locking here to prevent errors when Libevent is running in multiple threads.

Locks and threading

As you probably know if you’re writing multithreaded programs, it isn’t always safe to access the same data from multiple threads at the same time.

Libevent structures can generally work three ways with multithreading.

  • Some structures are inherently single-threaded: it is never safe to use them from more than one thread at the same time.某些结构体内在地是单线程的:同时在多个线程中使用它们总是不安全的。

  • Some structures are optionally locked: you can tell Libevent for each object whether you need to use it from multiple threads at once.某些结构体具有可选的锁:可以告知libevent 是否需要在多个线程中使用每个对象。

  • Some structures are always locked: if Libevent is running with lock support, then they are always safe to use from multiple threads at once.

    某些结构体总是锁定的:如果libevent 在支持锁的配置下运行,在多个线程中使用它们
    总是安全的。

To get locking in Libevent, you must tell Libevent which locking functions to use. You need to do this before you call any Libevent function that allocates a structure that needs to be shared between threads.

If you are using the pthreads library, or the native Windows threading code, you’re in luck. There are pre-defined functions that will set Libevent up to use the right pthreads or Windows functions for you.

为获取锁,在调用分配需要在多个线程间共享的结构体的libevent 函数之前,必须告知
libevent 使用哪个锁函数。

如果使用pthreads 库,或者使用Windows 本地线程代码,那么你是幸运的:已经有设置
libevent 使用正确的pthreads 或者Windows 函数的预定义函数。

转: libevent简单介绍

1      简介

主页:http://www.monkey.org/~provos/libevent/

libevent是一个事件触发的网络库,适用于windows、linux、bsd等多种平台,内部使用select、epoll、kqueue等系统调用管理事件机制。

编译库代码,编译脚本会判断OS支持哪种类型的事件机制(select、epoll或kqueue),然后条件编译相应代码,供上层使用的接口仍然是保持统一的。

libevent支持用户使用三种类型的事件,分别是网络IO、定时器、信号三种。定时器的数据结构使用最小堆(Min Heap),以提高效率。网络IO和信号的数据结构采用了双向链表(TAILQ)。在实现上主要有3种链表:EVLIST_INSERTED, EVLIST_ACTIVE, EVLIST_TIMEOUT,一个ev在这3种链表之间被插入或删除,处于EVLIST_ACTIVE链表中的ev最后将会被调度执行。

有许多开源项目使用libevent,例如memcached。使用libevent,使得memcached可以适应多种操作系统。Libevent对底层异步函数提供了较薄封装,库本身没有消耗过多性能;另外,使用堆排序管理定时器队列,提供了较高的性能。

2      使用介绍

2.1   网络IO

2.1.1  代码例子

//事件回调处理函数

Static void MyCallBack(const int fd, constshort which, void *arg)

{

If(EV_READ==which){

//读事件处理

}

……

}

Int main(int argc, char** argv)

{

//初始化libevent

struct event_base *pEventBase;

pEventBase =event_init();

intsock=socket(……);

struct eventevent;

event_set(&event , sock, EV_READ | EV_PERSIST,MyCallBack, (void*)0 );

event_base_set(pEventBase, &event);

event_add(&event, 0);

event_base_loop(pEventBase, 0);

Return0;

}

2.1.2  基本函数介绍

event_init:初始化libevent库。

event_set:赋值structevent结构。可以用event_add把该事件结构增加到事件循环,用event_del从事件循环中删除。支持的事件类型可以是下面组合:EV_READ(可读),  EV_WRITE(可写),EV_PERSIST(除非调用event_del,否则事件一直在事件循环中)。

event_base_set:修改structevent事件结构所属的event_base为指定的event_base。Libevnet内置一个全局的event_base结构。多个线程应用中,如果多个线程都需要一个libevent事件循环,需要调用event_base_set修改事件结构基于的event_base。

event_add:增加事件到事件监控中。

event_base_loop:事件循环。调用底层的select、poll或epoll等,如监听事件发生,调用事件结构中指定的回调函数。

2.2   定时器

2.2.1  代码例子

struct event g_clockevent;

struct event_base *g_pEventBase;

void clock_handler(const int fd, constshort which, void *arg)

{

staticbool initialized = false;

if(initialized) {

evtimer_del(&g_clockevent);

}

else {

initialized= true;

}

evtimer_set(&g_clockevent, clock_handler, (void*) 0);

//定时器时间

structtimeval t ;

t.tv_sec=1;

t.tv_usec=0;

event_base_set(g_pEventBase, &me->m_clockevent);

if(evtimer_add(&clock_handler, &t) == -1){

return;

}

//自定义事件处理

.....

}

int main(int argv, char** argc)

{

g_pEventBase=event_init();

clock_handler(0,0,(void*)0);

return0;

}

2.2.2  基本函数介绍

evtimer_set: 设置定时器事件。

evtimer_add: 增加定时器时间。

3      源代码简介

Libevent在底层select、pool、kqueue和epoll等机制基础上,封装出一致的事件接口。可以注册可读、可写、超时等事件,指定回调函数;当事件发生后,libevent调用回调函数,可以在回调函数里实现自定义功能。前面例子已经展现了如何使用libevent接口。

本节探讨一下libevent实现机制。

3.1   重要结构体

struct eventop:对select/pool/epoll/kqueue等底层函数,按照该结构提供的接口方式,封装接口统一的函数。

struct eventop {

constchar *name;

void*(*init)(struct event_base *);

int(*add)(void *, struct event *);

int(*del)(void*, struct event *);

int(*dispatch)(struct event_base *, void *, struct timeval *);

void(*dealloc)(struct event_base *, void *);

/*set if we need to reinitialize the event base */

intneed_reinit;

};

struct event_base:相当于一个事件池。一个线程一个。使用提供的API,把需要监控的事件结构加入到该事件池中。

struct event_base {

conststruct eventop *evsel;   //指向编译时选择的一个select/pool/epoll/kqueue接口封装对象。

void*evbase;

intevent_count;            /* counts numberof total events */

intevent_count_active;  /* counts number ofactive events */

intevent_gotterm;         /* Set to terminateloop */

intevent_break;            /* Set toterminate loop immediately */

/*active event management */

structevent_list **activequeues; //活动事件队列

intnactivequeues;

/*signal handling info */

structevsignal_info sig;

structevent_list eventqueue;  //监听事件队列

structtimeval event_tv;

structmin_heap timeheap; //定时器时间堆

structtimeval tv_cache;

};

线程事件循环使用底层机制异步监控事件。

struct event:事件结构。

struct event {

TAILQ_ENTRY(event) ev_next;

TAILQ_ENTRY(event) ev_active_next;

TAILQ_ENTRY(event) ev_signal_next;

unsignedint min_heap_idx;   /* for managingtimeouts */

structevent_base *ev_base;  //事件输入的evnet_base

intev_fd;

shortev_events;

shortev_ncalls;

short*ev_pncalls;   /* Allows deletes incallback */

structtimeval ev_timeout;

intev_pri;             /* smaller numbers arehigher priority */

void(*ev_callback)(int, short, void *arg);  //回调函数

void*ev_arg;

intev_res;             /* result passed toevent callback */

intev_flags;

};

3.2   主要函数介绍

按照使用libevnet库顺序,看一下相关函数做什么操作。

3.2.1  event_init

调用event_base_new,初始化struct event_base对象。

event_base_new里做了如下工作:

1、 申请内存

2、 初始化定时器堆和事件队列

3、 为event_base对象选择底层事件函数封装对象。根据编译选项,初始化eventops全局对象。该对象存放指向底层select/pool/epoll等功能的封装函数。

4、 初始化活动队列。

3.2.2  event_set

初始化structevent对象。

1、 把参数中指定初始化的事件对象的ev_base指向全局的current_base。

2、 赋值回调函数、描述符、监视事件等变量。

3.2.3  event_base_set

把struct event对象指向的event_base对象赋值为指定的对象。

event_set函数把event对象的ev_base指向全局的current_base,多线程环境下,如需要用自己的event_base对象,需要调用event_base_set重新指定event_base对象。

3.2.4  event_add

增加指定event到监控池里。

1、 对于读、写、信号事件,调用封装的add函数,调用底层select/pool/epoll相关函数,增加到操作系统事件监控里。对于epoll,调用的是epoll_add函数。Epoll_add函数调用epoll_ctl添加事件监控,libevent使用水平触发方式。把监听时间加入到event_base的事件队列中。

2、 对应定时器事件,加入到event_base的定时器最小堆里。

3、 对信号事件,调用evsignal_add,加入事件处理队列中。

3.2.5  event_base_loop

事件循环,事件发生后,调用相应回调函数。

1、 计算最近的超时时间:定时器最小堆按照超时时间排序,取最小的超时时间;如已有活动事件或指定不阻塞,超时时间为0。

2、 调用dispatch。对epoll,对应epoll_dispatch函数。该函数调用epoll_wait监控指定事件。

3、 把到了超时时间的时间加入到活动事件队列。从超时时间最小堆中依次取最小超时时间和当前时间比较,对小于/等于当前时间的事件,加入到活动事件队列。

4、 循环调用活动事件队列中所有事件的回调函数。

epoll_dispatch:

1.      计算epoll_wait函数需要的超时时间,把时间转换成微妙。

2.      如epoll_wait被信号中断,把相应信号对应的事件加入到活动事件队列。

3.      如监视的描述上发生了特定事件,把相应事件对象加入到活动事件队列。

更多:http://blog.csdn.net/funkri/article/details/9352955
参考:http://blog.csdn.net/mafuli007/article/details/7476014

libevent入门教程的更多相关文章

  1. [z]libevent入门教程:Echo Server based on libevent 不指定

    [z]https://www.felix021.com/blog/read.php?2068 花了两天的时间在libevent上,想总结下,就以写简单tutorial的方式吧,貌似没有一篇简单的说明, ...

  2. libevent 入门教程:Echo Server based on libevent(转)

    下面假定已经学习过基本的socket编程(socket, bind, listen, accept, connect, recv, send, close),并且对异步/callback有基本的认识. ...

  3. wepack+sass+vue 入门教程(三)

    十一.安装sass文件转换为css需要的相关依赖包 npm install --save-dev sass-loader style-loader css-loader loader的作用是辅助web ...

  4. wepack+sass+vue 入门教程(二)

    六.新建webpack配置文件 webpack.config.js 文件整体框架内容如下,后续会详细说明每个配置项的配置 webpack.config.js直接放在项目demo目录下 module.e ...

  5. wepack+sass+vue 入门教程(一)

    一.安装node.js node.js是基础,必须先安装.而且最新版的node.js,已经集成了npm. 下载地址 node安装,一路按默认即可. 二.全局安装webpack npm install ...

  6. Content Security Policy 入门教程

    阮一峰文章:Content Security Policy 入门教程

  7. gulp详细入门教程

    本文链接:http://www.ydcss.com/archives/18 gulp详细入门教程 简介: gulp是前端开发过程中对代码进行构建的工具,是自动化项目的构建利器:她不仅能对网站资源进行优 ...

  8. UE4新手引导入门教程

    请大家去这个地址下载:file:///D:/UE4%20Doc/虚幻4新手引导入门教程.pdf

  9. ABP(现代ASP.NET样板开发框架)系列之2、ABP入门教程

    点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之2.ABP入门教程 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)” ...

随机推荐

  1. windows 程序设计 SetPolyFillMode关于ALTERNATE、WINDING的详细解释

    看windows程序第五章GDI编程部分.一直卡壳在这里了. 下面我来说下自己的想法.看是否对您有帮助. 首先我们来看一个图. SetPolyFillMode(ALTERNATE);  // 系统默认 ...

  2. JAVA_SE复习(OOP2)

    面向对象编程(二) 一.static 关键字 静态属性 1.不能覆盖静态方法.要被覆盖的方法必须是非静态的.在继承链中具有相同方法名的两个静态方法是两个互相独立的类方法.调用子类的静态方法只是将父类的 ...

  3. 锋利的jquery-validation

    jquery插件 jquery插件项目托管于gitHub,项目地址https://github.com/jquery/plugins.jquery.com jquery插件的使用 表单验证插件 现在网 ...

  4. ios客户端base64上传图片到java服务器遇到的问题

    由于base64位包含了“+”和“\”两个特殊符号,导致ios编码后上传图片到服务器,服务器解码以后的值会不一致,导致图片损坏. 解决办法:重写Base64类,用“(”和“)”替换“+”和“\”两个特 ...

  5. linux乱码问题:LANG变量的秘诀

    对于国内的Linux用户,经常烦恼的一个问题是:系统常常在需要显示中文的时候却显示成了乱码,而由于某些原因,需要英文界面的系统的时候,却苦于系统不能正常输入和显示中文.另外,由于大部分主要Linux发 ...

  6. mysql优化之sakila测试数据库

    下载地址,选择相应的版本来进行安装测试 http://dev.mysql.com/doc/index-other.html 相关说明 http://dev.mysql.com/doc/sakila/e ...

  7. c#教程之事件处理函数的参数

    事件处理函数一般有两个参数,第一个参数(object sender)为产生该事件的对象的属性Name的值,例如上例单击标题为红色的按钮,第一个参数sender的值为button1.如上例标题为红色的按 ...

  8. EXTJS4.2 chart 柱状图

    chart 柱状图 Ext.require('Ext.chart.*'); Ext.require(['Ext.Window', 'Ext.fx.target.Sprite', 'Ext.layout ...

  9. Object c中的alloc和init问题

    从开始学的NSString *name=[[NSString alloc] init] 起,老师教这句话是分配内存空间,一直在用,从来没考虑过它的内部是怎么实现的.今天无意中看到了这一句代码 NSSt ...

  10. Lua中cJson的读写

    这里采用的是Lua CJson库,是一个高性能的JSON解析器和编码器,其性能比纯Lua库要高10~20倍.并且Lua Json完全支持UTF-8,无需以来其他非Lua/LuaJit相关包. 环境安装 ...