1. libevent到底使用哪种io模式来作为底层实现
libevent实际封装了很多IO复用模式,比如evport,select,poll,epoll,devpoll等等,这些都是不同操作系统下的I/O多路复用模式,那么我们怎么知道当前使用的是哪种模式呢?
说到底层实现,那就不得不说说event-config.h文件的生成。
1.1 event-config.h文件的生成
在上一篇《libevent目录结构分析》中,我们提到event-config.h,它存放了很多宏定义配置。
event-config.h这个文件并不是一直不变的,这里有一个过程:
- 首先,configure在检查环境依赖的时候会生成config.h和Makefile;
- 然后,Makefile会根据config.h生成event-config.h;
event-config.h基本是存放宏定义的,如下:
/* Define to 1 if you have the <dlfcn.h> header file. */
#define EVENT__HAVE_DLFCN_H 1
/* Define if your system supports the epoll system calls */
#define EVENT__HAVE_EPOLL 1
/* Define to 1 if you have the `epoll_create1' function. */
/* #undef EVENT__HAVE_EPOLL_CREATE1 */
/* Define to 1 if you have the `epoll_ctl' function. */
#define EVENT__HAVE_EPOLL_CTL 1
/* Define to 1 if you have the <errno.h> header file. */
#define EVENT__HAVE_ERRNO_H 1
这个是在我的redhat环境下编译以后生成的部分宏定义,EVENT__HAVE_EPOLL这个宏定义为1则说明我的redhat环境是支持epoll的,但这并不能说明我当前就是使用的epoll,因为redhat同样支持select和poll。
1.2 I/O模式选择
那么底层实现到底用哪个呢,看下面代码:
struct event_config *config;
struct event_base *base;
/* Create a new configuration object. */
config = event_config_new();
/* We don't want to use the "select" method. */
event_config_avoid_method(config, "select");
/* We want a method that can work with non-socket file descriptors */
event_config_require_features(config, EV_FEATURE_FDS);
base = event_base_new_with_config(config)