对于信号事件的监听,比较不同的是,不是每一个信号有一个event,然后放进内核中去监听。而是对于所有信号,共用一个信号事件event去监听,当有信号来临时,使用管道将信号写进去,libevent通过这个event来监听这个管道,然后当这个管道有数据读的时候,这个event的回调函数就是遍历管道中的信号,然后分别将该信号的事件处理器添加到激活队列中。
1. 信号捕捉函数与管道
struct event_base {
const struct eventop *evsigsel;
struct evsig_info sig;
...
struct event_signal_map sigmap;
...
};
//evsignal-internal.h文件
struct evsig_info {
//用于监听socketpair读端的event. ev_signal_pair[1]为读端
struct event ev_signal;
//socketpair
evutil_socket_t ev_signal_pair[2];
//用来标志是否已经将ev_signal这个event加入到event_base中了
int ev_signal_added;
//用户一共要监听多少个信号
int ev_n_signals_added;
//数组。用户可能已经设置过某个信号的信号捕抓函数。但
//Libevent还是要为这个信号设置另外一个信号捕抓函数,
//此时,就要保存用户之前设置的信号捕抓函数。当用户不要
//监听这个信号时,就能够恢复用户之前的捕抓函数。
//因为是有多个信号,所以得用一个数组保存。
#ifdef _EVENT_HAVE_SIGACTION
struct sigaction **sh_old;
#else//保存的是捕抓函数的函数指针,又因为是数组。所以是二级指针
ev_sighandler_t **sh_old;
#endif
/* Size of sh_old. */
int sh_old_max; //数组的长度
}
typedef void (*ev_sighandler_t)(int); //此为函数指针
//设置信号抓捕函数
int
evsig_set_handler_(struct event_base *base,
int evsignal, void (__cdecl *handler)(int))
{
//如果有sigaction就优先使用
#ifdef EVENT__HAVE_SIGACTION
struct sigaction sa;
#else
ev_sighandler_t sh;
#endif
struct evsig_info *sig = &base->sig;
void *p;
/*
* resize saved signal handler array up to the highest signal number.
* a dynamic array is used to keep footprint on the low side.
*/
if (evsignal >= sig->sh_old_max) {
int new_max = evsignal + 1;
event_debug(("%s: evsignal (%d) >= sh_old_max (%d), resizing",
__func__, evsignal, sig->sh_old_max));
p = mm_realloc(sig->sh_old, new_max * sizeof(*sig->sh_old));
if (p == NULL) {
event_warn("realloc");
return (-1);
}
memset((char *)p + sig->sh_old_max * sizeof(*sig->sh_old),
0, (new_max - sig->sh_old_max) * sizeof(*sig->sh_old));
sig->sh_old_max = new_max;
sig->sh_old = p;
}
//为这个数组中的一级指针分配内存
/* allocate space for previous handler out of dynamic array */
sig->sh_old[evsignal] = mm_malloc(sizeof *sig->sh_old[evsignal]);
if (sig->sh_old[evsignal] == NULL) {
event_warn("malloc");
return (-1);
}
/* save previous handler and setup new handler */
#ifdef EVENT__HAVE_SIGACTION
memset(&sa, 0, sizeof(sa));
sa.sa_handler = handler;
sa.sa_flags |= SA_RESTART;
sigfillset(&sa.sa_mask);
//设置信号处理函数,并将之前的保存起来
if (sigaction(evsignal, &sa, sig->sh_old[evsignal]) == -1) {
event_warn("sigaction");
mm_free(sig->sh_old[evsignal]);
sig->sh_old[evsignal] = NULL;
return (-1);
}
#else
//设置信号处理函数
if ((sh = signal(evsignal, handler)) == SIG_ERR) {
event_warn