概述
在linux系统中有现成的信号捕获接口如sigaction,它可以捕获指定的信号并执行用户自定义信号处理函数,那么如何将这种机制集成到libevent事件管理模型中呢?
libevent采用了socketpair的方式将信号事件集成到了其自身的事件处理模型中。
具体做法如下简述:
- 初始化socketpair;
- 调用接口sigaction设置指定信号的信号处理函数,该信号处理函数所做工作为向socketpair的写端写入捕获的信号号;
- 将socketpair的读端对应的事件添加到libevent事件管理模型中(读端其实就是一个IO事件),读端事件的回调函数所做工作是读取写端写入的信号号并激活用户的signal事件,将其添加到libevent活跃事件队列等待执行;
libevent具体实现
1、 libevent库初始化,使用以下两个接口初始化event库,并且初始化一个event
struct event_base * event_base_new(void);// 该接口内初始化了socketpair
/* Initalize one event */
signal_int = evsignal_new(base, SIGINT, signal_cb, event_self_cbarg());;
2、添加signal事件到event
int event_add(struct event *ev, const struct timeval *tv);
对于signal事件,该接口所做主要工作:
1)、和添加IO事件一样,以信号号为下标添加信号事件到libevent库中;
int evmap_signal_add_(struct event_base *base, int sig, struct event *ev)
2)、添加socketpair读端IO事件到libevent库中;
static int evsig_add(struct event_base *base, evutil_socket_t evsignal, short old, short events, void *p)
3)、设置信号处理函数
int evsig_set_handler_(struct event_base *base, int evsignal, void (__cdecl *handler)(int))
3、 进入事件主循环
int event_base_dispatch(struct event_base *event_base);
当捕获到信号时,信号处理函数将信号号写入socketpair写端,在事件主循环中调用接口
res = evsel->dispatch(base, tv_p);
捕获到此次写事件,激活上述读端IO事件,在读端IO事件中获取写端传来的信号号,将该信号号对应的信号事件添加到活跃事件链表等待执行。