【传智播客】Libevent学习笔记(二):创建event_base
00. 目录
声明: 该博客来源于传智播客C++学院相关培训参考手册
01. 简介
使用libevent函数之前需要分配一个或者多个event_base结构体。每个event_base结构体持有一个事件集合,可以检测以确定哪个事件是激活的。
如果设置event_base使用锁,则可以安全地在多个线程中访问它。然而,其事件循环只能运行在一个线程中。如果需要用多个线程检测IO,则需要为每个线程使用一个event_base。
每个event_base都有一种用于检测哪种事件已经就绪的“方法”,或者说后端。可以识别的方法有:
- select
- poll
- epoll
- kqueue
- devpoll
- evport
- win32
用户可以用环境变量禁止某些特定的后端。比如说,要禁止kqueue后端,可以设置EVENT_NOKQUEUE环境变量。如果要用编程的方法禁止后端,请看下面关于event_config_avoid_method()的说明。
02. 创建默认的event_base
event_base_new()函数分配并且返回一个新的具有默认设置的event_base。函数会检测环境变量,返回一个到event_base的指针。如果发生错误,则返回NULL。选择各种方法时,函数会选择操作系统支持的最快方法。
函数相关说明:
/**
* Create and return a new event_base to use with the rest of Libevent.
*
* @return a new event_base on success, or NULL on failure.
*
* @see event_base_free(), event_base_new_with_config()
*/
struct event_base *event_base_new(void);
功能:
创建一个默认属性的struct event_base对象
参数:
无
返回值:
成功: 返回struct event_base结构体指针
失败: NULL
event_base_new()函数声明在<event2/event.h>中,首次出现在libevent 1.4.3版。
大多数情况下, 我们创建默认的event_base就可以满足我们的需求。
03. 创建复杂的event_base
要对取得什么类型的event_base有更多的控制,就需要使用event_config。
event_config是一个容纳event_base配置信息的不透明结构体。需要event_base时,将event_config传递给event_base_new_with_config()。
相关头文件: libevent-2.0.22-stable/include/event2/event.h
3.1 event_config_new函数
/**
Allocates a new event configuration object.
The event configuration object can be used to change the behavior of
an event base.
@return an event_config object that can be used to store configuration, or
NULL if an error is encountered.
@see event_base_new_with_config(), event_config_free(), event_config
*/
struct event_config *event_config_new(void);
功能:
分配一个event_config
参数:
无
返回值:
成功:返回struct event_config结构体指针
失败:NULL
3.2 event_base_new_with_config函数
/**
Initialize the event API.
Use event_base_new_with_config() to initialize a new event base, taking
the specified configuration under consideration. The configuration object
can currently be used to avoid certain event notification mechanisms.
@param cfg the event configuration object
@return an initialized event_base that can be used to registering events,
or NULL if no event base can be created with the requested event_config.
@see event_base_new(), event_base_free(), event_init(), event_assign()
*/
struct event_base *event_base_new_with_config(const struct event_config * cfg);
功能:
初始化一个新的event_base
参数:
cfg event_config结构体指针
返回值:
成功:返回一个可以用于注册事件的初始化好的event_base对象
失败:NULL
3.3 event_config_free函数
/**
Deallocates all memory associated with an event configuration object
@param cfg the event configuration object to be freed.
*/
void event_config_free(struct event_config *cfg);
功能:
释放event_config对象
参数:
cfg event_config_new函数的返回值
返回值:
无
3.4 event_config_avoid_method函数
/**
Enters an event method that should be avoided into the configuration.
This can be used to avoid event mechanisms that do not support certain
file descriptor types, or for debugging to avoid certain event
mechanisms. An application can make use of multiple event bases to
accommodate incompatible file descriptor types.
@param cfg the event configuration object
@param method the name of the event method to avoid
@return 0 on success, -1 on failure.
*/
int event_config_avoid_method(struct event_config *cfg, const char *method);
功能:
可以通过名字让libevent避免使用特定的可用后端。
参数:
cfg event_config对象指针
method 避免使用特定的后端
返回值:
成功 0
失败 -1
3.5 event_config_require_features函数
/**
Enters a required event method feature that the application demands.
Note that not every feature or combination of features is supported
on every platform. Code that requests features should be prepared
to handle the case where event_base_new_with_config() returns NULL, as in:
<pre>
event_config_require_features(cfg, EV_FEATURE_ET);
base = event_base_new_with_config(cfg);
if (base == NULL) {
// We can't get edge-triggered behavior here.
event_config_require_features(cfg, 0);
base = event_base_new_with_config(cfg);
}
</pre>
@param cfg the event configuration object
@param feature a bitfield of one or more event_method_feature values.
Replaces values from previous calls to this function.
@return 0 on success, -1 on failure.
@see event_method_feature, event_base_new_with_config()
*/
int event_config_require_features(struct event_config *cfg, int feature);
功能:
设置libevent不使用不能提供所有指定特征的后端。
参数:
cfg event_config结构体指针
feature 指定特征的后端
返回值:
成功 0
失败 -1
指定特征的后端
/**
A flag used to describe which features an event_base (must) provide.
Because of OS limitations, not every Libevent backend supports every
possible feature. You can use this type with
event_config_require_features() to tell Libevent to only proceed if your
event_base implements a given feature, and you can receive this type from
event_base_get_features() to see which features are available.
*/
enum event_method_feature {
/** Require an event method that allows edge-triggered events with EV_ET. */
EV_FEATURE_ET = 0x01,
/** Require an event method where having one event triggered among
* many is [approximately] an O(1) operation. This excludes (for
* example) select and poll, which are approximately O(N) for N
* equal to the total number of possible events. */
EV_FEATURE_O1 = 0x02,
/** Require an event method that allows file descriptors as well as
* sockets. */
EV_FEATURE_FDS = 0x04
};
event_config_require_features()可识别的特征值有:
EV_FEATURE_ET:要求支持边沿触发的后端。
EV_FEATURE_O1:要求添加、删除单个事件,或者确定哪个事件激活的操作是O(1)复杂度的后端。
EV_FEATURE_FDS:要求支持任意文件描述符,而不仅仅是套接字的后端。
3.6 event_config_set_flag函数
/**
* Sets one or more flags to configure what parts of the eventual event_base
* will be initialized, and how they'll work.
*
* @see event_base_config_flags, event_base_new_with_config()
**/
int event_config_set_flag(struct event_config *cfg, int flag);
功能:
设置让libevent在创建event_base时设置一个或者多个将在下面介绍的运行时标志。
参数:
cfg event_config结构体指针
flag 指定的标志
返回值:
成功 0
失败 -1
对应的标志有
/**
A flag passed to event_config_set_flag().
These flags change the behavior of an allocated event_base.
@see event_config_set_flag(), event_base_new_with_config(),
event_method_feature
*/
enum event_base_config_flag {
/** Do not allocate a lock for the event base, even if we have
locking set up. */
EVENT_BASE_FLAG_NOLOCK = 0x01,
/** Do not check the EVENT_* environment variables when configuring
an event_base */
EVENT_BASE_FLAG_IGNORE_ENV = 0x02,
/** Windows only: enable the IOCP dispatcher at startup
If this flag is set then bufferevent_socket_new() and
evconn_listener_new() will use IOCP-backed implementations
instead of the usual select-based one on Windows.
*/
EVENT_BASE_FLAG_STARTUP_IOCP = 0x04,
/** Instead of checking the current time every time the event loop is
ready to run timeout callbacks, check after each timeout callback.
*/
EVENT_BASE_FLAG_NO_CACHE_TIME = 0x08,
/** If we are using the epoll backend, this flag says that it is
safe to use Libevent's internal change-list code to batch up
adds and deletes in order to try to do as few syscalls as
possible. Setting this flag can make your code run faster, but
it may trigger a Linux bug: it is not safe to use this flag
if you have any fds cloned by dup() or its variants. Doing so
will produce strange and hard-to-diagnose bugs.
This flag can also be activated by settnig the
EVENT_EPOLL_USE_CHANGELIST environment variable.
This flag has no effect if you wind up using a backend other than
epoll.
*/
EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST = 0x10
};
event_config_set_flag()可识别的选项值有:
EVENT_BASE_FLAG_NOLOCK:不要为event_base分配锁。设置这个选项可以为event_base节省一点用于锁定和解锁的时间,但是让在多个线程中访问event_base成为不安全的。
EVENT_BASE_FLAG_IGNORE_ENV:选择使用的后端时,不要检测EVENT_*环境变量。使用这个标志需要三思:这会让用户更难调试你的程序与libevent的交互。
EVENT_BASE_FLAG_STARTUP_IOCP:仅用于Windows,让libevent在启动时就启用任何必需的IOCP分发逻辑,而不是按需启用。
EVENT_BASE_FLAG_NO_CACHE_TIME:不是在事件循环每次准备执行超时回调时检测当前时间,而是在每次超时回调后进行检测。注意:这会消耗更多的CPU时间。
EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST:告诉libevent,如果决定使用epoll后端,可以安全地使用更快的基于changelist的后端。epoll-changelist后端可以在后端的分发函数调用之间,同样的fd多次修改其状态的情况下,避免不必要的系统调用。但是如果传递任何使用dup()或者其变体克隆的fd给libevent,epoll-changelist后端会触发一个内核bug,导致不正确的结果。在不使用epoll后端的情况下,这个标志是没有效果的。也可以通过设置EVENT_EPOLL_USE_CHANGELIST环境变量来打开epoll-changelist选项。
注意:
设置event_config,请求OS不能提供的后端是很容易的。比如说,对于libevent 2.0.1-alpha,在Windows中是没有O(1)后端的;在Linux中也没有同时提供EV_FEATURE_FDS和EV_FEATURE_O1特征的后端。如果创建了libevent不能满足的配置,event_base_new_with_config()会返回NULL。
3.7 event_config_set_num_cpus_hint函数
函数当前仅在Windows上使用IOCP时有用,虽然将来可能在其他平台上有用。这个函数告诉event_config在生成多线程event_base的时候,应该试图使用给定数目的CPU。注意这仅仅是一个提示:event_base使用的CPU可能比你选择的要少。
/**
* Records a hint for the number of CPUs in the system. This is used for
* tuning thread pools, etc, for optimal performance. In Libevent 2.0,
* it is only on Windows, and only when IOCP is in use.
*
* @param cfg the event configuration object
* @param cpus the number of cpus
* @return 0 on success, -1 on failure.
*/
int event_config_set_num_cpus_hint(struct event_config *cfg, int cpus);
功能:
设置试图给定数目的CPU。
参数:
cfg event_config结构体指针
cpus CPU数量
返回值:
成功 0
失败 -1
官方参考示例:
struct event_config *cfg;
struct event_base *base;
int i;
/* My program wants to use edge-triggered events if at all possible. So
I'll try to get a base twice: Once insisting on edge-triggered IO, and
once not. */
for (i=0; i<2; ++i) {
cfg = event_config_new();
/* I don't like select. */
event_config_avoid_method(cfg, "select");
if (i == 0)
event_config_require_features(cfg, EV_FEATURE_ET);
base = event_base_new_with_config(cfg);
event_config_free(cfg);
if (base)
break;
/* If we get here, event_base_new_with_config() returned NULL. If
this is the first time around the loop, we'll try again without
setting EV_FEATURE_ET. If this is the second time around the
loop, we'll give up. */
}
总述:
以上函数和类型在<event2/event.h>中声明。
EVENT_BASE_FLAG_IGNORE_ENV标志首次出现在2.0.2-alpha版本。event_config_set_num_cpus_hint()函数是2.0.7-rc版本新引入的。本节的其他内容首次出现在2.0.1-alpha版本。
04. 检查event_base的后端
有时候需要检查event_base支持哪些特征,或者当前使用哪种方法。
4.1 event_get_supported_methods函数
/**
Gets all event notification mechanisms supported by Libevent.
This functions returns the event mechanism in order preferred by
Libevent. Note that this list will include all backends that
Libevent has compiled-in support for, and will not necessarily check
your OS to see whether it has the required resources.
@return an array with pointers to the names of support methods.
The end of the array is indicated by a NULL pointer. If an
error is encountered NULL is returned.
*/
const char **event_get_supported_methods(void);
功能:
获取当前系统支持的后端。
参数:
无
返回值:
成功 返回一个指针,指向libevent支持的方法名字数组
失败 NULL
参考程序:
#include <stdio.h>
#include <event.h>
int main(void)
{
int i = 0;
const char **pstr = event_get_supported_methods();
if (NULL == pstr)
{
printf("event_get_supported_methods failed...\n");
return 1;
}
printf("Libevent version: %s\n", event_get_version());
for (i = 0; NULL != pstr[i]; i++)
{
printf("\t%s\n", pstr[i]);
}
return 0;
}
执行结果:
注意:
这个函数返回libevent被编译以支持的方法列表。然而libevent运行的时候,操作系统可能不能支持所有方法。比如说,可能OS X版本中的kqueue的bug太多,无法使用。
4.2 event_base_get_method函数
/**
Get the kernel event notification mechanism used by Libevent.
@param eb the event_base structure returned by event_base_new()
@return a string identifying the kernel event mechanism (kqueue, epoll, etc.)
*/
const char *event_base_get_method(const struct event_base *base);
功能:
获取当前base使用的后端。
参数:
base event_base对象
返回值:
成功 返回一个指针,指向使用的后端。
失败 NULL。
参考示例:
#include <stdio.h>
#include <event.h>
int main(void)
{
struct event_base *base = NULL;
//创建一个对象
base = event_base_new();
if (NULL == base)
{
printf("event_base_new failded...\n");
return 1;
}
printf("methods: %s\n", event_base_get_method(base));
//释放对象
event_base_free(base);
return 0;
}
执行结果:
4.3 event_base_get_features函数
/**
Return a bitmask of the features implemented by an event base. This
will be a bitwise OR of one or more of the values of
event_method_feature
@see event_method_feature
*/
int event_base_get_features(const struct event_base *base);
功能:
返回event_base支持的特征的比特掩码。
参数:
base event_base对象
返回值:
成功 特征的比特掩码。
失败 0。
参考代码:
#include <stdio.h>
#include <event.h>
int main(void)
{
struct event_base *base = NULL;
enum event_method_feature f;
base = event_base_new();
if (NULL == base)
{
printf("event_base_new failded...\n");
return 1;
}
f = event_base_get_features(base);
if ((f & EV_FEATURE_ET))
printf(" Edge-triggered events are supported.");
if ((f & EV_FEATURE_O1))
printf(" O(1) event notification is supported.");
if ((f & EV_FEATURE_FDS))
printf(" All FD types are supported.");
printf("\n");
event_base_free(base);
return 0;
}
执行结果:
05. 释放event_base
使用完event_base之后,使用event_base_free()进行释放。
/**
Deallocate all memory associated with an event_base, and free the base.
Note that this function will not close any fds or free any memory passed
to event_new as the argument to callback.
@param eb an event_base to be freed
*/
void event_base_free(struct event_base *base);
功能:
释放base
参数:
base event_base对象
返回值:
无
参考代码:
#include <stdio.h>
#include <event.h>
int main(void)
{
struct event_base *base = NULL;
//创建base对象
base = event_base_new();
if (NULL == base)
{
printf("event_base_new failded...\n");
return 1;
}
//释放base
event_base_free(base);
return 0;
}
注意:
这个函数不会释放当前与event_base关联的任何事件,或者关闭他们的套接字,或者释放任何指针。
event_base_free()定义在<event2/event.h>中,首次由libevent 1.2实现。
06. 设置event_base的优先级
libevent支持为事件设置多个优先级。然而,event_base默认只支持单个优先级。可以调用event_base_priority_init()设置event_base*的优先级数目。
event_base_priority_init函数
/**
Set the number of different event priorities
By default Libevent schedules all active events with the same priority.
However, some time it is desirable to process some events with a higher
priority than others. For that reason, Libevent supports strict priority
queues. Active events with a lower priority are always processed before
events with a higher priority.
The number of different priorities can be set initially with the
event_base_priority_init() function. This function should be called
before the first call to event_base_dispatch(). The
event_priority_set() function can be used to assign a priority to an
event. By default, Libevent assigns the middle priority to all events
unless their priority is explicitly set.
Note that urgent-priority events can starve less-urgent events: after
running all urgent-priority callbacks, Libevent checks for more urgent
events again, before running less-urgent events. Less-urgent events
will not have their callbacks run until there are no events more urgent
than them that want to be active.
@param eb the event_base structure returned by event_base_new()
@param npriorities the maximum number of priorities
@return 0 if successful, or -1 if an error occurred
@see event_priority_set()
*/
int event_base_priority_init(struct event_base *base, int pri);
功能:
设置base优先级
参数:
base event_base对象
pri 这个数目至少是1。每个新的事件可用的优先级将从0(最高)pri-1(最低)。
返回值:
成功 0
失败 -1
/** Largest number of priorities that Libevent can support. */
#define EVENT_MAX_PRIORITIES 256
常量EVENT_MAX_PRIORITIES表示pri的上限。调用这个函数时为pri给出更大的值是错误的。
注意:
必须在任何事件激活之前调用这个函数,最好在创建event_base后立刻调用。
关于示例,请看event_priority_set的文档。
默认情况下,与event_base相关联的事件将被初始化为具有优先级pri/ 2。event_base_priority_init()函数定义在<event2/event.h>中,从libevent 1.0版就可用了。
07. fork之后重新初始化base
不是所有事件后端都在调用fork()之后可以正确工作。所以,如果在使用fork()或者其他相关系统调用启动新进程之后,希望在新进程中继续使用event_base,就需要进行重新初始化。
event_reinit函数
/**
Reinitialize the event base after a fork
Some event mechanisms do not survive across fork. The event base needs
to be reinitialized with the event_reinit() function.
@param base the event base that needs to be re-initialized
@return 0 if successful, or -1 if some events could not be re-added.
@see event_base_new()
*/
int event_reinit(struct event_base *base);
功能:
重新初始化base
参数:
base event_base对象
返回值:
成功 0
失败 -1
官方参考示例
struct event_base *base = event_base_new();
/* ... add some events to the event_base ... */
if (fork()) {
/* In parent */
continue_running_parent(base); /*...*/
} else {
/* In child */
event_reinit(base);
continue_running_child(base); /*...*/
}
event_reinit()定义在<event2/event.h>中,在libevent 1.4.3-alpha版中首次可用。
08. 参考
相关书籍: http://www.wangafu.net/~nickm/libevent-book/Ref2_eventbase.html
官方参考网站: https://www.monkey.org/~provos/libevent/doxygen-2.0.1/index.html
【传智播客】Libevent学习笔记(二):创建event_base的更多相关文章
- 传智播客Springmvc_mybatis学习笔记
文件地址:https://download.csdn.net/download/qq_26078953/10614459
- 传智播客JavaWeb day02笔记
2015年1月21日 今天的主要内容:介绍了几款常用Javaweb服务器,重点介绍了tomcat以及tomcat的安装和怎么样检测安装成功 1.JavaWeb常见服务器 Tomcat(免费但是只支持部 ...
- 《2013传智播客视频》-wmv,avi,mp4.目录
\!--14俄罗斯方块\视频\.复习.avi; \!--14俄罗斯方块\视频\ 复习.avi; \!--14俄罗斯方块\视频\ 形状旋转.avi; \!--14俄罗斯方块\视频\ 判断形状能否变形.a ...
- 【传智播客】Libevent学习笔记(三):事件循环
目录 00. 目录 01. event_base_loop函数 02. event_base_dispatch函数 03. event_base_loopexit函数 04. event_base_l ...
- 【传智播客】Libevent学习笔记(五):基本类型和函数
目录 00. 目录 01. 基本类型 1.1 evutil_socket_t类型 1.2 标准类型 1.3 各种兼容性类型 02. 可移植的定时器函数 03. 套接字API兼容性 04. 可移植的字符 ...
- 【传智播客】Libevent学习笔记(四):事件event
目录 00. 目录 01. 事件概述 02. 创建事件 03. 事件的标志 04. 事件持久性 05. 超时事件 06. 信号事件 07. 设置不使用堆分配的事件 08. 事件的未决和非未决 09. ...
- 传智播客.NET视频学习课件
传智播客.NET视频学习课件访问.NET网站了解更多课程详情http://net.itcast.cn(小提示:为什么本书中超链接打不开?)此套课件是伴随 传智播客.net实况教学视频 (小提示:为什么 ...
- 传智播客学习之Android运行原理 (转)
传智播客学习之Android运行原理 (2010-03-20 22:45:15) 转载▼ 今天终于忙里偷闲,和大家探讨一下android技术,第一次听到3G应该追溯到大学三年级的时候了,记得当时现代通 ...
- 传智播客C语言视频第二季(第一季基础上增加诸多C语言案例讲解,有效下载期为10.5-10.10关闭)
卷 backup 的文件夹 PATH 列表卷序列号为 00000025 D4A8:14B0J:.│ 1.txt│ c语言经典案例效果图示.doc│ ├─1传智播客_尹成_C语言从菜鸟到高手_第一 ...
随机推荐
- bzoj 4698: Sdoi2008 Sandy的卡片【SAM】
差分之后用SAM求LCS,然后答案就是LCS+1 #include<iostream> #include<cstdio> #include<cstring> usi ...
- 【杂谈】5G有啥用?跟咱有关系么?关注那玩意儿干啥?
用处大了 有啥用? 云计算啊,你看看你电脑都卡成啥了? 既然5G速度赶上本地读取,那就相当于把硬盘放云端没问题了.那么,看看自己硬盘里都有啥,5G的用处或许就能一点点浮现出来了. ——请不要急着打开一 ...
- IT兄弟连 JavaWeb教程 ServletContext对象
ServletContext是Servlet与Servlet容器之间直接通信的接口.Servlet容器在启动一个Web应用时,会为它创建一个ServletContext对象.每个Web应用都有唯一的S ...
- Ubuntu开机之后报错结局方法
sudo gedit /etc/default/apport 把里面的enabled=1改成enabled=,保存 201. 就是下雨也去.202. 我马上拿来.203. 孙英开飞机.204. 国华来 ...
- Incorrect string value: '\xE8\x8B\x8F\xE6\x99\xA8...' for column 'user_name' at row 1
前端插入数据的时候报如下错误: Incorrect string value: '\xE8\x8B\x8F\xE6\x99\xA8...' for column 'user_name' at row ...
- KMP算法笔记(云笔记图片版)
- 记忆化搜索(DFS+DP) URAL 1223 Chernobyl’ Eagle on a Roof
题目传送门 /* 记忆化搜索(DFS+DP):dp[x][y] 表示x个蛋,在y楼扔后所需要的实验次数 ans = min (ans, max (dp[x][y-i], dp[x-1][i-1]) + ...
- 牛客国庆集训派对Day_4~6
Day_4 A.深度学习 题目描述 小 A 最近在研究深度学习,他自己搭建了一个很牛逼的神经网络,现在他手头一共有 n 组训练数据,一开始他会给自己的神经网络设置一个 batch size,假设为 B ...
- linux/centos系统如何使用yum安装vi/vim?
yum安装vim最简单的命令, yum -y install vim* 然后就可以使用vi命令了. 网上的文章: 要使用vim, 使用yum看了一下,发现有4个 vim-common.i386 ...
- HTTP协议 处理流程
我们平时在浏览网页的时候都是使用浏览器,输入你要的网址后回车,就会显示出我们所想要的内容,看似这个简单的用户操作行为的背后,Web的工作原理是怎样的呢?到底隐藏了些什么呢? 对于传统的上网流程,系统它 ...