libevent学习——event_base

这篇具有很好参考价值的文章主要介绍了libevent学习——event_base。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

event_base

使用 libevent 函数之前需要分配一个或者多个 event_base 结构体。每个event_base 结构 体持有一个事件集合,可以检测以确定哪个事件是激活的。

如果设置 event_base 使用锁,则可以安全地在多个线程中访问它 。然而,其事件循环只能 运行在一个线程中。如果需要用多个线程检测 IO,则需要为每个线程使用一个 event_base

每个 event_base 都有一种用于检测哪种事件已经就绪的 “方法”,或者说后端。可以识别的方法有:

  • select
  • poll
  • epoll
  • kqueue
  • devpoll
  • evport
  • win32

创建event_base

创建默认的event_base

event_base_new()函数分配并且返回一个新的具有默认设置的 event_base。函数会检测环境变量,返回一个到 event_base 的指针。如果发生错误,则返回 NULL。选择各种方法时,函数会选择 OS 支持的最快方法。

struct event_base *event_base_new(void);

大多数程序使用这个函数就够了。

创建复杂的event_base

要对取得什么类型的 event_base 有更多的控制,就需要使用 event_config
event_config 是一个容纳 event_base 配置信息的不透明结构体。需要 event_base时,将 event_config 传递给event_base_new_with_config()

创建接口:

struct event_config *event_config_new(void);
struct event_base *
event_base_new_with_config(const struct event_config *cfg);
void event_config_free(struct event_config *cfg);

要使用这些函数分配 event_base,先调用 event_config_new()分配一个event_config。 然后,对 event_config 调用其它函数,设置所需要的 event_base 特征。最后,调用 event_base_new_with_config()获取新的 event_base。完成工作后,使用 event_config_free()释放 event_config

/**
   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.
*/
EVENT2_EXPORT_SYMBOL
int event_config_avoid_method(struct event_config *cfg, const char *method);

/**
   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,
    /** Require an event method that allows you to use EV_CLOSED to detect
     * connection close without the necessity of reading all the pending data.
     *
     * Methods that do support EV_CLOSED may not be able to provide support on
     * all kernel versions.
     **/
    EV_FEATURE_EARLY_CLOSE = 0x08
};

/**
   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.

	    Setting this option will make it unsafe and nonfunctional to call
	    functions on the base concurrently from multiple threads.
	*/
	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 setting 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,

	/** Ordinarily, Libevent implements its time and timeout code using
	    the fastest monotonic timer that we have.  If this flag is set,
	    however, we use less efficient more precise timer, assuming one is
	    present.
	 */
	EVENT_BASE_FLAG_PRECISE_TIMER = 0x20
};

/**
   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()
*/
EVENT2_EXPORT_SYMBOL
int event_config_require_features(struct event_config *cfg, int feature);

/**
 * 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()
 **/
EVENT2_EXPORT_SYMBOL
int event_config_set_flag(struct event_config *cfg, int flag);

调用 event_config_avoid_method()可以通过名字让 libevent 避免使用特定的可用后端 。 调用 event_config_require_feature()让 libevent 不使用不能提供所有指定特征的后端。 调用 event_config_set_flag()让 libevent 在创建 event_base 时设置一个或者多个将在下面介绍的运行时标志。
event_config_require_features()可识别的特征值有:

  • EV_FEATURE_ET:要求支持边沿触发的后端
  • EV_FEATURE_O1:要求添加、删除单个事件,或者确定哪个事件激活的操作是O(1)复杂度的后端
  • EV_FEATURE_FDS:要求支持任意文件描述符,而不仅仅是套接字的后端

event_config_set_flag()可识别的选项值有:

  • EVENT_BASE_FLAG_NOLOCK :不要为 event_base 分配锁。设置这个选项可以为 event_base 节省一点用于锁定和解锁的时间,但是让在多个线程中访问event_base 成为不安全的。
  • EVENTBASE_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 的函数都在成功时返回0,失败时返回-1。

设置 event_config,请求 OS 不能提供的后端是很容易的 。比如说,对于 libevent2.0.1-alpha, 在 Windows 中是没有 O(1)后端的;在 Linux 中也没有同时提供EV_FEATURE_FDS 和 EV_FEATURE_O1 特征的后端。如果创建了 libevent不能满足的配置, event_base_new_with_config ()会返回 NULL。

检查event_base后端

有时候需要检查 event_base 支持哪些特征,或者当前使用哪种方法。

/**
   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.
*/
EVENT2_EXPORT_SYMBOL
const char **event_get_supported_methods(void);

event_get_supported_methods()函数返回一个指针 ,指向 libevent 支持的方法名字数组。这个数组的最后一个元素是 NULL
实例:

int i;
const char** methods = event_get_supported_methods();
printf("Starting Libevent %s.
       Available methods are
       :\n ",
       event_get_version());
for (i = 0; methods[i] != NULL; ++i) {
printf("
 %s\n", methods[i]);
}

这个函数返回 libevent 被编译以支持的方法列表 。然而 libevent 运行的时候,操作系统可能 不能支持所有方法。比如说,可能 OS X 版本中的 kqueue 的 bug太多,无法使用。

const char *
event_base_get_method(const struct event_base *base);
enum event_method_feature
event_base_get_features(const struct event_base *base);

event_base_get_method()返回 event_base 正在使用的方法。
event_base_get_features()返回 event_base 支持的特征的比特掩码。

实例:文章来源地址https://www.toymoban.com/news/detail-732955.html

struct event_base* base;
enum event_method_feature f;
base = event_base_new();
if (!base) {
    puts("Couldn't get an event_base!");
} else {
    printf("Using Libevent with backend method %s.",
        event_base_get_method(base));
    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.");
puts("");
}

释放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.

  If there are any pending finalizer callbacks, this function will invoke
  them.

  @param eb an event_base to be freed
 */
EVENT2_EXPORT_SYMBOL
void event_base_free(struct event_base *);

注意:这个函数不会释放当前与 event_base 关联的任何事件,或者关闭他们的套接字, 或者释放任何指针。

event_base优先级

libevent支持为事件设置多个优先级。然而, event_base默认只支持单个优先级。可以调用 event_base_priority_init()设置 event_base 的优先级数目。

/**
  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()
 */
EVENT2_EXPORT_SYMBOL
int	event_base_priority_init(struct event_base *, int);

成功时这个函数返回 0,失败时返回 -1。base 是要修改的 event_base,n_priorities是要支持的优先级数目,这个数目至少是 1 。每个新的事件可用的优先级将从 0 (最高) 到 n_priorities-1(最低)。
常量 EVENT_MAX_PRIORITIES 表示 n_priorities 的上限。调用这个函数时为n_priorities 给出更大的值是错误的。

必须在任何事件激活之前调用这个函数,最好在创建 event_base 后立刻调用。

event_base和fork

不是所有事件后端都在调用 fork()之后可以正确工作。所以,如果在使用 fork()或者其 他相关系统调用启动新进程之后,希望在新进程中继续使用 event_base,就需要进行重新初始化。

/**
  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()
*/
EVENT2_EXPORT_SYMBOL
int event_reinit(struct event_base *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); /*...*/
}

到了这里,关于libevent学习——event_base的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【tensorboard】深度学习的日志信息events.out.tfevents文件可视化工具

    在用深度学习模型训练完模型后,会有一些events.out.tfevents格式的日志信息文件,如下图: 在这类文件需要用tensorboard进行打开,并且查看训练过程的信息内容。 命令格式为: 注意:日志所在的目录是指日志的目录文件夹,不是日志本身路径。 以上面图片中为例,命令为:

    2024年02月12日
    浏览(51)
  • 【SimPy系列博客之官方example学习与解读】—— Example 4: Event Latency

    Hello,CSDN的各位小伙伴们,又见面啦!今天我们要学习的例程是:Event Latency!我们开始吧! 今天这个example比较好玩,有点类似于网络中的通信。我们要实现的是一个简单的point-to-point的消息收发机制。其中,sender源源不断地通过电缆cable给另一端的receiver发送消息,然而消息

    2024年01月15日
    浏览(258)
  • libevent高并发网络编程 - 04_libevent实现http服务器

    链接: C/C++Linux服务器开发/后台架构师【零声教育】-学习视频教程-腾讯课堂 在libevent中,HTTP的实现主要是通过 evhttp 模块来完成的。 evhttp 提供了一个高层次的HTTP服务器接口,可以处理HTTP请求并发送HTTP响应。 在源码中,libevent的HTTP协议处理主要是通过 evhttp 模块来完成的。

    2024年02月15日
    浏览(37)
  • html5学习笔记19-SSE服务器发送事件(Server-Sent Events)

    https://www.runoob.com/html/html5-serversentevents.html 允许网页获得来自服务器的更新。类似设置回调函数。 demo_sse.php demo_sse.aspx

    2024年02月09日
    浏览(51)
  • libevent介绍和使用

    libevent 是一个开源的事件通知库,它提供了一个跨平台的抽象接口,libevnet处理的事件包括网络IO事件,定时事件以及信号事件。它可以在不同的操作系统上使用,包括Linux、Windows和Mac OS X等。libevent 的主要目的是提供高效的事件通知机制,用户无需关注平台检测处理事件的机

    2024年02月04日
    浏览(43)
  • libevent常用的API函数

    使用libevent函数之前需要分配一个或多个event_base结构体,每个event_base结构体持有一个事件集合,可以检测以确定是哪个事件激活的,event_base相当于epoll红黑树的树根节点。 函数说明:获得event_base结构体; 返回值:成功返回指向event_base结构体的指针 失败返回NULL. /**  * Crea

    2024年03月15日
    浏览(37)
  • 基于libevent的tcp服务器

    libevent使用教程_evutil_make_socket_nonblocking_易方达蓝筹的博客-CSDN博客 centos7下安装libevent库 server.cpp  client.cpp

    2024年02月11日
    浏览(42)
  • Libevent开源库的介绍与应用

    libevent https://libevent.org/ 一、初识 1、libevent介绍 Libevent 是一个用C语言编写的、轻量级的开源高性能事件通知库,主要有以下几个亮点:事件驱动( event-driven),高性能;轻量级,专注于网络,不如 ACE 那么臃肿庞大;源代码相当精炼、易读;跨平台,支持 Windows、 Linux、 *BSD

    2024年02月14日
    浏览(39)
  • libevent:windows环境配置+QT使用

    目录 libevent是什么 编译 QT使用 测试代码 Fast portable non-blocking network programming with Libevent http://www.wangafu.net/~nickm/libevent-book/TOC.html 这篇文档讲的很清楚,尤其是Chapter 1: A tiny introduction to asynchronous IO.,基本上讲清楚了大多数的内容 环境: 1、win10 64位 2、vs2015专业版(nmake)/Cmake 3、

    2024年02月16日
    浏览(34)
  • libevent实践06:监听TCP服务器

    参数解析: base:事件集合  evconnlistener_cb:cb是call back的缩写,就是回调函数定义如下: ptr:传递给cb的参数 flags:属性标志位,可取值9个(掰手指头数的),下面是9个取值的宏定义,在evconnlistener_new_bind函数源码中也可以看出来。 backlog:设置监听队列的大小,同listen函数的

    2024年02月12日
    浏览(64)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包