libevent入门教程
首先给出官方文档吧: 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 使用一个工具分配器,以便检查内存泄漏时,可能需要这
样做。Interfacevoid 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入门教程的更多相关文章
- [z]libevent入门教程:Echo Server based on libevent 不指定
[z]https://www.felix021.com/blog/read.php?2068 花了两天的时间在libevent上,想总结下,就以写简单tutorial的方式吧,貌似没有一篇简单的说明, ...
- libevent 入门教程:Echo Server based on libevent(转)
下面假定已经学习过基本的socket编程(socket, bind, listen, accept, connect, recv, send, close),并且对异步/callback有基本的认识. ...
- wepack+sass+vue 入门教程(三)
十一.安装sass文件转换为css需要的相关依赖包 npm install --save-dev sass-loader style-loader css-loader loader的作用是辅助web ...
- wepack+sass+vue 入门教程(二)
六.新建webpack配置文件 webpack.config.js 文件整体框架内容如下,后续会详细说明每个配置项的配置 webpack.config.js直接放在项目demo目录下 module.e ...
- wepack+sass+vue 入门教程(一)
一.安装node.js node.js是基础,必须先安装.而且最新版的node.js,已经集成了npm. 下载地址 node安装,一路按默认即可. 二.全局安装webpack npm install ...
- Content Security Policy 入门教程
阮一峰文章:Content Security Policy 入门教程
- gulp详细入门教程
本文链接:http://www.ydcss.com/archives/18 gulp详细入门教程 简介: gulp是前端开发过程中对代码进行构建的工具,是自动化项目的构建利器:她不仅能对网站资源进行优 ...
- UE4新手引导入门教程
请大家去这个地址下载:file:///D:/UE4%20Doc/虚幻4新手引导入门教程.pdf
- ABP(现代ASP.NET样板开发框架)系列之2、ABP入门教程
点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之2.ABP入门教程 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)” ...
随机推荐
- iOS编程——经过UUID和KeyChain来代替Mac地址实现iOS设备的唯一标示(OC版)
iOS编程——通过UUID和KeyChain来代替Mac地址实现iOS设备的唯一标示(OC版) 很多的应用都需要用到手机的唯一标示,而且要求这个唯一标示不能因为应用app的卸载或者改变而变化. 在iO ...
- 使用fiddler4做代理调试手机页面
由于一般手机不能改host,手机页面如果涉及到各个域名ip的混合使用,在手机上调试看效果非常麻烦. 使用fiddler4做代理,手机跟电脑连到同一个局域网,手机上网通过电脑做个代理上网,那么一切请求就 ...
- javascript实现暂停
<!DOCTYPE HTML><html> <head> <title> New Document </title> <meta ...
- 用AJAX自定义日历
需求分析 在一些购物网站中,都会有促销活动,这些活动都在日历上标注出来,如何通过Ajax让日历 通过读取数据库中的信息,正确的把促销活动标注在日历上,本文通过自定义日历来实现这 个问题. 技术难点 日 ...
- sizeof的用法的一些归纳
1 sizeof 是运算符,不是函数 2 sizeof 不能求得void类型的长度,能求得 void*类型的指针的长度 sizeof(void) 会导致编译错误.因为声明一个变量的最重要的作用就是告诉 ...
- [旧博客]QQ旋风加速漏洞
漏洞是这样的,用开通QQ会员的账号登录QQ旋风,添加要下载的任务,启动加速后,注销,登录lixian.qq.com 删除刚才添加的离线任务,这时QQ旋风还是在加速那个任务.而你又可以登录QQ旋风添加其 ...
- unity 3d-Easy Touch 3教程 转
Easy Touch 教程 转自:http://www.unitymanual.com/thread-31332-1-1.html 1.import “Easy Touch 3”的资源包 2.创建人物 ...
- 1059. Prime Factors (25)
时间限制 50 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 HE, Qinming Given any positive integer N, y ...
- (转)Qt Model/View 学习笔记 (三)——Model类
Model类 基本概念 在model/view构架中,model为view和delegates使用数据提供了标准接口.在Qt中,标准接口QAbstractItemModel类中被定义.不管数据在底层以 ...
- 关于postgresql——常用操作指令
创建数据库 CREATE DATABASE test WITH OWNER = postgres ENCODING = 'UTF8'; 进入控制台方法,在postgreSQL的安装目的bin下执行命令 ...