Libevent--信号事件

        对于信号事件的监听,比较不同的是,不是每一个信号有一个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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值