(转)Libevent(1)— 简介、编译、配置
转自:http://name5566.com/4190.html
参考文献列表:
http://www.wangafu.net/~nickm/libevent-book/
此文编写的时候,使用到的 Libevent 为 2.0.21
Libevent 之跨平台
在处理大量 SOCKET 连接时,使用 select 并不高效。各个系统都提供了处理大量 SOCKET 连接时的解决方案:
- Linux 下的 epoll()
- BSD 下的 kqueue()
- Solaris 下的 evports
- Windows 下的 IOCP
由于各个平台使用了不同的接口,那么我们需要编写跨平台的高性能异步程序时就需要做一层跨平台封装。
这个时候 Libevent 就成为一个较好的选择,其最底层 API(event 和 event_base API)为各个平台实现高性能异步程序提供了一致的接口。
Libevent 2 提供的 bufferevent 接口,一方面简化了编程的难度,另一方面保证了在 Windows 和 Unix 上都很高效。
一些基本的概念
- event 会绑定文件描述符、回调函数并表示一个或者多个条件(例如,文件描述符可以读或者写了、发生了超时等)。event 表示的条件如果被触发了,那么 event 会变为活跃的,它绑定的回调函数就会被执行
- event_base 用于持有一组 event 并进行事件循环,event_base 会存在一个后端(也叫做方法),常见的后端包括 epoll、kqueue 等
Libevent 的结构
组件:
- evutil 用于抽象不同的平台的网络(基础的)实现
- event、event_base 为 Libevent 的核心,为不同的平台下基于事件的非阻塞 I/O 提供了一套抽象的接口
- bufferevent 对 Libevent 的基于事件的核心的封装。应用程序的读写请求是基于缓冲区的
- evbuffer 为 bufferevent 实现的缓冲区
- evhttp 一个简单的 HTTP client/server 的实现
- evdns 一个简单的 DNS client/server 的实现
- evrpc 一个简单的 RPC 实现
库:
- libevent_core 包括 util、event_base、evbuffer、bufferevent
- libevent_extra 包括 HTTP、DNS、RPC
- libevent 此库由于历史原因而存在,不要使用它
- libevent_pthreads 此库为基于 pthread 的线程和锁的实现
- libevent_openssl 此库通过 openssl 和 bufferevent 提供了加密通讯
头文件:
所有的公用头文件位于 event2 目录中。
编译 Libevent 库
Linux 下编译的方式为(详细见 README):
- $ ./configure
- $ make
常用的 configure 标志有:
- --disable-shared 只编译静态库
- --disable-openssl 关闭 OpenSSL 加密支持
Windows 下编译的方式为:
- nmake /f Makefile.nmake
需要注意的是,虽然官方提供了此 makefile,但是此文件尚未编写完善(详见 Makefile.nmake 的注释)
编译完成之后,需要将 WIN32-Code 目录加入到 VS 的 include paths 中去
设置 Libevent 库
在具体的介绍之前,这里首先需要明确的一点是,我们总是先设置 Libevent,然后才去使用 Libevent。
关于输出日志的设置
Libevent 的日志信息默认被写入 stderr(标准错误),我们可以提供自己的日志处理函数给 Libevent:
- // 日志的类型
- #define EVENT_LOG_DEBUG 0
- #define EVENT_LOG_MSG 1
- #define EVENT_LOG_WARN 2
- #define EVENT_LOG_ERR 3
- // 日志处理函数原型
- // severity 参数对应了上面的各种日志类型
- typedef void (*event_log_cb)(int severity, const char *msg);
- // 设置一个新的日志处理函数
- void event_set_log_callback(event_log_cb cb);
设置日志处理函数的范例:
- #include <event2/event.h>
- #include <stdio.h>
- static void discard_cb(int severity, const char *msg)
- {
- // 此函数不做任何事情
- }
- static FILE *logfile = NULL;
- static void write_to_file_cb(int severity, const char *msg)
- {
- const char *s;
- if (!logfile)
- return;
- switch (severity) {
- case _EVENT_LOG_DEBUG: s = "debug"; break;
- case _EVENT_LOG_MSG: s = "msg"; break;
- case _EVENT_LOG_WARN: s = "warn"; break;
- case _EVENT_LOG_ERR: s = "error"; break;
- default: s = "?"; break; /* never reached */
- }
- fprintf(logfile, "[%s] %s\n", s, msg);
- }
- // 关闭 Libevent 的日志信息的输出
- void suppress_logging(void)
- {
- event_set_log_callback(discard_cb);
- }
- // 设置 Libevent 的日志信息输出到特定文件
- void set_logfile(FILE *f)
- {
- logfile = f;
- event_set_log_callback(write_to_file_cb);
- }
关于日志的注意事项:
- 日志处理函数中不要调用任何的 Libevent 函数
- Debug 日志信息默认不会被输出,一般也不需要
Libevent 处理致命错误的做法是调用 exit() 或者 abort() 函数,你可以修改此行为(例如,你希望此时输出调用栈信息):
- typedef void (*event_fatal_cb)(int err);
- void event_set_fatal_callback(event_fatal_cb cb);
注意事项:
- 我们定义的 event_fatal_cb 函数不要将控制权再返回给 Libevent
- 不要在 event_fatal_cb 函数中调用任何的 Libevent 函数
为 Libevent 定义自己的内存管理器
默认的情况下 Libevent 使用 C 库的内存管理函数从堆上分配内存。替换 Libevent 默认内存管理函数主要有以下几个目的:
- 更加高效的分配内存
- 检测内存泄漏
设置自己定义的内存管理函数:
- void event_set_mem_functions(void *(*malloc_fn)(size_t sz),
- void *(*realloc_fn)(void *ptr, size_t sz),
- void (*free_fn)(void *ptr));
替换 Libevent 内存管理函数时需要注意的地方:
- 正如前面说到的,所有设置应该在 Libevent 被使用之前完成,对于内存管理的配置来说更加是如此,否则可能引起崩溃
- 你设定的内存管理函数必须是线程安全的
- 你设定的 malloc 和 realloc 返回的内存地址的对齐需要和 C 库一致
- 你设定的 realloc 需要能够处理 realloc(NULL, sz)
- 你设定的 realloc 需要能够处理 realloc(ptr, 0)
关闭和清理
我们关闭程序的时候,需要完成一些清理工作:
- void libevent_global_shutdown(void);
此函数在 2.1.1-alpha 才被引入。
Libevent 多线程的问题
如果你希望 Libevent 函数分配的结构能够被多个线程共享,那么首先需要告知 Libevent 我们使用的锁定函数。如果使用 pthreads 库或者使用 Windows 线程,可以调用以下函数来进行设置:
- // 这两个函数成功返回 0 失败返回 -1
- #ifdef WIN32
- int evthread_use_windows_threads(void);
- #define EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED
- #endif
- #ifdef _EVENT_HAVE_PTHREADS
- int evthread_use_pthreads(void);
- #define EVTHREAD_USE_PTHREADS_IMPLEMENTED
- #endif
void evthread_enable_lock_debuging(void) 函数可以让 Libevent 通过 assert 告知我们关于锁的一些错误信息,主要是告知我们解锁了一个未持有的锁。我们需要在任意一个锁被创建或使用之前调用此函数。
void event_enable_debug_mode(void) 函数可以让 Libevent 检测 event 使用上的一些错误:
- 认为一个未初始化的 event 已经初始化了
- 尝试重新初始化一个 pending event(pending event 为一个术语,之后的文章会谈到)
注意的是,开启 debug 模式(也就是调用 event_enable_debug_mode)后,会有额外的内存和 CPU 开销,所以应该在真正调试的时候再开启。event_enable_debug_mode 函数需要在任意的 event_base 被创建前调用。
(转)Libevent(1)— 简介、编译、配置的更多相关文章
- Linux内核分析(一)---linux体系简介|内核源码简介|内核配置编译安装
原文:Linux内核分析(一)---linux体系简介|内核源码简介|内核配置编译安装 Linux内核分析(一) 从本篇博文开始我将对linux内核进行学习和分析,整个过程必将十分艰辛,但我会坚持到底 ...
- 转载:Centos7 从零编译配置Memcached
序言 Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度. Memca ...
- [原创]Centos7 从零编译配置Memcached
序言 Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度. Memca ...
- Nginx 反向代理工作原理简介与配置详解
Nginx反向代理工作原理简介与配置详解 by:授客 QQ:1033553122 测试环境 CentOS 6.5-x86_64 nginx-1.10.0 下载地址:http://nginx. ...
- 【内核】linux2.6版本内核编译配置选项(一)
Linux 2.6.19.x 内核编译配置选项简介 作者:金步国 版权声明 本文作者是一位自由软件爱好者,所以本文虽然不是软件,但是本着 GPL 的精神发布.任何人都可以自由使用.转载.复制和再分发, ...
- Linux防火墙简介 – iptables配置策略
Linux防火墙简介 – iptables配置策略 Netfilter/iptables简介 要想真正掌握Linux防火墙体系,首先要搞清楚Netfilter和iptables的关系,Netfilte ...
- 深入浅出Mybatis系列(六)---objectFactory、plugins、mappers简介与配置
上篇文章<深入浅出Mybatis系列(五)---TypeHandler简介及配置(mybatis源码篇)>简单看了一下TypeHandler, 本次将结束对于mybatis的配置文件的学习 ...
- MyBatis学习(一)、MyBatis简介与配置MyBatis+Spring+MySql
一.MyBatis简介与配置MyBatis+Spring+MySql 1.1MyBatis简介 MyBatis 是一个可以自定义SQL.存储过程和高级映射的持久层框架.MyBatis 摒除了大部分的J ...
- Fast RCNN 训练自己数据集 (1编译配置)
FastRCNN 训练自己数据集 (1编译配置) 转载请注明出处,楼燚(yì)航的blog,http://www.cnblogs.com/louyihang-loves-baiyan/ https:/ ...
- MyBatis学习 之 一、MyBatis简介与配置MyBatis+Spring+MySql
目录(?)[-] 一MyBatis简介与配置MyBatisSpringMySql MyBatis简介 MyBatisSpringMySql简单配置 搭建Spring环境 建立MySql数据库 搭建My ...
随机推荐
- 关于arm处理器 内存编址模式 与 字节对齐方式 (转)
转自:http://bavon.bokee.com/5429805.html 在x86+Linux上写的程序,在PC机上运行得很好.可是使用ARM的gcc进行交叉编译,再送到DaVinci目标板上运行 ...
- SQLite 入门教程(二)创建、修改、删除表 (转)
转于 SQLite 入门教程(二)创建.修改.删除表 一.数据库定义语言 DDL 在关系型数据库中,数据库中的表 Table.视图 View.索引 Index.关系 Relationship 和触发器 ...
- @ContextConfiguration注解说明
@ContextConfiguration Spring整合JUnit4测试时,使用注解引入多个配置文件单个文件 @ContextConfiguration(Locations="../ap ...
- Apache CXF框架结构和基本原理(转)
原文链接:http://blog.sina.com.cn/s/blog_6182547f01017pak.html CXF旨在为服务创建必要的基础设施,它的整体架构主要由以下几个部分组成: 1.Bus ...
- 树莓派(Rospberry Pi B+)到货亲測
1 图鉴 Rospberry Pi B+最终在今天下午有蜗牛快递公司圆*送到了.B+主要是添加了2个USB,添加了GPIO,sd卡换成了micro sd ...先不说直接上图再说,期待了好久好久 w ...
- android学习二(Activity)
前面我简单的介绍了android的一些基础知识,当作热身吧,接下来接触android的四大组件的activity活动. 1.活动Activity是是一种保护用户界面的组件,主要用于和用户进行交互. 活 ...
- 职责链模式vs状态模式区别
状态模式在具体状态里设置了下一状态. 而职责链模式是在客户端代码里设置了下一状态的处理对象. 如果状态模式里的任何一环缺失,将导致事情无法进行下去.职责链模式的链式在客户端连接的,也就是说,如果我们请 ...
- android105 jni概念
JNI(Java Native Interface,JAVA原生接口) ,通过JNIjava代码可以调用C代码,JNI在安卓中用的很多.安卓中的框架层就是用过JNI访问类库层的.Iphone是用C/C ...
- Socket异步通信学习一
最近在做一个频谱管理项目,负责通信模块,自己也是小白,重头学起,直至今天通信基本框架已经完成,把自己在学习中的心得与大家分享一下,做一个socket系列的博文,顺便加固一下自己对socket通信的认识 ...
- iOS之layout方法-layoutSubviews、layoutIfNeeded、setNeedsLayout
下面列举下iOS layout的相关方法: layoutSubviews layoutIfNeeded setNeedsLayout setNeedsDisplay drawRect sizeThat ...