libevent 学习分享

来源:互联网 发布:js ajax请求乱码 编辑:程序博客网 时间:2024/04/29 09:33

  • libevent简介

首先简单介绍一下libevent,它是一个开源的轻量级网络库,具有良好的跨平台特性,支持Linux, FreeBSD, OpenBSD, NetBSD, Mac OS X, Solaris, Android等各种平台,支持多种不同的I/O多路复用机制。它采用的是基于事件驱动(event-driven)的模型,这里的事件包括有:I/O,定时器,信号等。

  • 阅读基础
学习过基本的socket编程(socket,bind,listen,accept,connect,recv,send,close),并且对异步/callback有基本认识。基本的socket编程是阻塞/同步的,每个操作除非已经完成或者出错才会返回,这样对于每一个请求,要使用一个线程或者单独的进程去处理,系统资源没法支撑大量的请求(所谓c10k problem?),例如内存:默认情况下每个线程需要占用2~8M的栈空间。posix定义了可以使用异步的select系统调用,但是因为其采用了轮询的方式来判断某个fd是否变成active,效率不高[O(n)],连接数一多,也还是撑不住。于是各系统分别提出了基于异步/callback的系统调用,例如Linux的epoll,BSD的kqueue,Windows的IOCP。由于在内核层面做了支持,所以可以用O(1)的效率查找到active的fd。基本上,libevent就是对这些高效IO的封装,提供统一的API,简化开发。

event和event_base是其最核心的部分。

event_base

一、创建event_base

有两种方式。

第一,默认方式创建;

[cpp] view plaincopyprint?
  1. struct event_base *event_base_new(void);  

默认情况下,libevent会选择该平台下效率最高的I/O多路复用机制作为其backend使用的method。

第二,自定义方式创建;

[cpp] view plaincopyprint?
  1. struct event_config *event_config_new(void);  
  2. struct event_base *event_base_new_with_config(const struct event_config *cfg);  
  3. void event_config_free(struct event_config *cfg);  
首先,调用event_config_new()函数创建一个event_config对象,然后调用下面即将讲到的几个接口来指定method属性,再调用event_base_new_with_config()创建对应的event_base,创建完以后,event_config就没用了,别忘了释放掉。libevent为我们提供的这些接口函数有:

[cpp] view plaincopyprint?
  1. int event_config_avoid_method(struct event_config *cfg, const char *method);  
  2.   
  3. int event_config_require_features(struct event_config *cfg, enum event_method_feature feature);  
  4.   
  5. int event_config_set_flag(struct event_config *cfg, enum event_base_config_flag flag);  

第一个,很直白地告诉libevent不希望使用哪个method,传入参数就是method的名字,比如说"epoll";

第二个,告诉libevent需要支持哪些features,包括有:

    EV_FEATURE_ET 支持边沿触发方式(epoll)

    EV_FEATURE_O1 事件插入删除查找的时间复杂度均为O(1)(epoll)

    EV_FEATURE_FDS 支持任意的文件描述符,不止socket一种(select、poll)

第三个,设置flag,具体这里不再一一说明。

需要明确的是,上面三个接口函数若成功均返回0,-1则表示失败。

若平台没有满足指定要求的method,调用event_base_new_with_config()将返回NULL表示失败。

二、销毁event_base

方法很简单,直接调用函数

[cpp] view plaincopyprint?
  1. void event_base_free(struct event_base *base);  

三、设置event_base的优先级

相关接口函数有:

[cpp] view plaincopyprint?
  1. int event_base_priority_init(struct event_base *base, int n_priorities);  
  2.   
  3. int event_base_get_npriorities(struct event_base *base);  

调用第一个函数,优先级被设置为0~n_priorities-1,其中0表示最高。

第二个函数返回的是该event_base所支持的事件优先级个数。

四、其它辅助函数

[cpp] view plaincopyprint?
  1. const char **event_get_supported_methods(void);  

获取本平台所支持的所有methods。

!注意:这个函数返回的是一个字符串数组,内存空间是由该函数申请的,但不需要程序员去手动释放(如果手动释放的话,也不会出现bug)。(具体原因见代码实现)

[cpp] view plaincopyprint?
  1. const char *event_base_get_method(const struct event_base *base);  

获取本event_base的backend所使用的method。

[cpp] view plaincopyprint?
  1. enum event_method_feature event_base_get_features(const struct event_base *base);  
获取本event_base的backend所使用的method属性。返回的是对应的bitmask值。
0 0
原创粉丝点击