Libevent学习----信号事件

信号是一种异步事件:信号处理函数和程序的主循环是两条不同的执行路线。很明显,信号处理函数需要尽可能快地执行完毕,以确保该信号不被屏蔽太久(信号在处理期间,系统不会再次触发它)。
这里写图片描述
上面这幅图是网上找到的,很好地从整体上表述了原理,摘抄到最前面
下图是本人自己总结的信号事件代码级原理图
这里写图片描述

这里写图片描述

下面是展开分析代码实现

一、初始化信号事件
调用base->evbase = base->evsel->init(base); 实际就是调用epoll_init, base->evbase最终指向了epollop结构,
在epoll_init的最后,调用了evsig_init.
/*设置观察ev_signal_pair[1]的event事件ev_signal, 事件类型为EV_READ|EV_PERSIST,
* 这个event将加入到evmap_io数组中
并且设置信号的统一处理函数evsig_cb/

/* Data structure for the default signal-handling implementation in signal.c
 */
struct evsig_info {
    /* Event watching ev_signal_pair[1] */
    struct event ev_signal;/*观察ev_signal_pair[1]的event事件*/
    /* Socketpair used to send notifications from the signal handler */
    evutil_socket_t ev_signal_pair[2];
    /* True iff we've added the ev_signal event yet. */
    int ev_signal_added;
    /* Count of the number of signals we're currently watching. */
    int ev_n_signals_added;

    /* Array of previous signal handler objects before Libevent started
     * messing with them.  Used to restore old signal handlers. */
#ifdef _EVENT_HAVE_SIGACTION
    struct sigaction **sh_old;
#else
    ev_sighandler_t **sh_old;
#endif
    /* Size of sh_old. */
    int sh_old_max;
};


/*此函数主要用于设置event base结构里面的struct evsig_info sig*/
 *struct evsig_info主要用于实现通用的信号处理
 *创建unix socket一端fd对应的event,并将其保存在base->sig.ev_signal事件 
 *中,在第一次调用event_add添加信号的时候,将ev_signal事件加入I/O事件处理 */
int
evsig_init(struct event_base *base)
{
    /*
     * Our signal handler is going to write to one end of the socket
     * pair to wake up our event loop.  The event loop then scans for
     * signals that got delivered.
     */
     /*创建一对unix套接字,用于传递信号值*/
    if (evutil_socketpair(
            AF_UNIX, SOCK_STREAM, 0, base->sig.ev_signal_pair) == -1) {
#ifdef WIN32
        /* Make this nonfatal on win32, where sometimes people
           have localhost firewalled. */
        event_sock_warn(-1, "%s: socketpair", __func__);
#else
        event_sock_err(1, -1, "%s: socketpair", __func__);
#endif
        return -1;
    }
    /*设置unix套接字的exec执行时关闭*/
    evutil_make_socket_closeonexec(base->sig.ev_signal_pair[0]);
    evutil_make_socket_closeonexec(base->sig.ev_signal_pair[1]);
    base->sig.sh_old = NULL;
    base->sig.sh_old_max = 0;

    /*设置unix套接字为非阻塞套接字*/
    evutil_make_socket_nonblocking(base->sig.ev_signal_pair[0]);
    evutil_make_socket_nonblocking(base->sig.ev_signal_pair[1]);
    /*设置观察ev_signal_pair[1]的event事件ev_signal, 事件类型为EV_READ|EV_PERSIST,
       * 这个event将加入到evmap_io数组中
     *并且设置信号的统一处理函数evsig_cb*/
    event_assign(&base->sig.ev_signal, base, base->sig.ev_signal_pair[1],
        EV_READ | EV_PERSIST, evsig_cb, base);

    base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL;
    /*保证信号的处理进入第一优先级队列*/
    event_priority_set(&base->sig.ev_signal, 0);
    /*设置evsigsel*/
    base->evsigsel = &evsigops;

    return 0;
}

二、创建信号事件

#define evsignal_new(b, x, cb, arg)
    event_new((b), (x), EV_SIGNAL|EV_PERSIST, (cb), (arg))

主要的区别在于此处的x(fd)为signal值, events类型为EV_SIGNAL | EV_PERSIST.

/*
* 该函数完成了 1、event内存的分配; 2、设置可所属的event_base; 
* 3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值