libevent学习笔记【使用篇】——2. 获取(创建)event_base

来源:互联网 发布:数据库压力测试工具 编辑:程序博客网 时间:2024/05/22 15:18

  • event_base 的使用
    • 默认event_base 和 高级event_base
    • 创建和释放默认的event_base
  • 事件注册
      • EV_PERSIST 和 EV_ET
      • 关于timeout和signal事件

文章出处: http://blog.csdn.net/windeal3203/article/details/52770270
翻译自:http://www.wangafu.net/~nickm/libevent-book/Ref2_eventbase.html

在使用任何libevent库函数之前,需要分配至少一个struct event_base的对象。每一个struct event_base对象都维护者一系列事件,并且能够轮询是是否有事件被激活。

如果对event_base进行了加锁的保护,那么他可以被多线程访问,我们只需要在某一个线程中运行轮询。 但是如果我们需要各个线程都能进行自己IO轮询,那么就需要为每个线程分配一个event_base.

每个event_base都有一个轮询的方法,目前我们已认知的方法有:

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

libevent 支持启用或禁用其中的method

event_base 的使用

默认event_base 和 高级event_base

  • 默认的event_base: 根据当前的运行环境,创建一个通用的event_base。
  • 高级的event_base: 可以通过配置文件等方式对event 配置一些高级选项。
    对于大多数程序而言,默认的event_base已经足够。

创建和释放默认的event_base

struct event_base *event_base_new(void);void event_base_free(struct event_base *base);

事件注册

libevent是一个事件驱动库,它主要是封装了事件发生的通知机制。那么,什么事件?下面是一些常见的事件:

  • 文件描述符已经可读、可写
  • 文件描述符正在变得可读、可写(边沿触发)
  • 超时
  • 信号发生
  • 用户触发的事件

当事件发生时,我们可能做一些特别的处理(执行某个函数)。 libevent提供了事件的注册机制,让开发者将事件与事件处理函数关联在一起,并绑定到event_base中。 从程序上看,libevent是创建了一个struct event的对象。该对象与event_base事件回调函数关联到了一起。也就是说,我们通过这个struct event对象,就可以知道什么事件发生时,才执行什么动作。

#define EV_TIMEOUT      0x01#define EV_READ         0x02#define EV_WRITE        0x04#define EV_SIGNAL       0x08#define EV_PERSIST      0x10#define EV_ET           0x20typedef void (*event_callback_fn)(evutil_socket_t, short, void *);struct event *event_new(struct event_base *base, evutil_socket_t fd,    short what, event_callback_fn cb,    void *arg);void event_free(struct event *event);

关键函数在于event_new, 它把事件、event_base、回调函数关联到一起了。
这里比较不好理解的是参数 fdwhat

  • fd:, 要关注的文件描述符,即我们关心的是哪个文件描述符上的事件。
  • what:表示关注的是哪一类事件,取值是上面定义的标志位:宏EV_TIMEOUTEV_READ等。
    fdwhat对应的事件发生时,回调函数cb就会被调用。 参数arg是需要传递给回调函数cb的参数。

通过event_new构建的事件,,我们已经知道了事件发生时该做什么, 那么怎么及时知道事件什么时候发生了。libevent提供了将事件设置为pending状态的方式,(所谓pengding状态,指的是一旦触发事件发生的条件具备时,就通知程序事件发生了)。libevent通过以下接口实现:

int event_add(struct event *ev, const struct timeval *tv);  // makes event pending in its configured baseint event_del(struct event *ev);  //non-pending and non-active.

EV_PERSIST 和 EV_ET

前面提到了一些flag宏, EV_TIMEOUT等都是用与指示监听的事件,但EV_PERSISTEV_ET不太一样
+ EV_PERSIST:在默认情况下(不设置EV_PERSIST),事件发生,执行回调函数时,事件会自动变成non-pending状态,需要重新执行event_add()如果设置了EV_PERSIST标志,则事件会一直处于pending状态
+ EV_ET:表示边沿触发。

关于timeout和signal事件

关于这两类事件,出了event_XXX的函数接口外,libevent提供了更直接的接口
timout

#define evtimer_new(base, callback, arg) \    event_new((base), -1, 0, (callback), (arg))#define evtimer_add(ev, tv) \    event_add((ev),(tv))#define evtimer_del(ev) \    event_del(ev)#define evtimer_pending(ev, tv_out) \    event_pending((ev), EV_TIMEOUT, (tv_out))

signal

#define evsignal_new(base, signum, cb, arg) \    event_new(base, signum, EV_SIGNAL|EV_PERSIST, cb, arg)#define evsignal_add(ev, tv) \    event_add((ev),(tv))#define evsignal_del(ev) \    event_del(ev)#define evsignal_pending(ev, what, tv_out) \    event_pending((ev), (what), (tv_out))
0 0
原创粉丝点击