在libevent中通过使用socketpair建立一对流管道,也就是全双工管道,来将信号事件与句柄事件统一起来。
先来看数据结构:
struct evsignal_info {
struct event ev_signal; ///<所属的event
int ev_signal_pair[2]; ///<创建的流管道
int ev_signal_added; ///<信号是否已被加入到event中的标记。
volatile sig_atomic_t evsignal_caught; ///<事件触发标记,1表示有信号被触发
struct event_list evsigevents[NSIG]; ///<多个事件有可能注册到同一个信号,因此这里每个信号的事件都是一个event_list.
sig_atomic_t evsigcaught[NSIG]; ///<由于一个信号可能被注册多次,这里保存信号被捕捉的次数
#ifdef HAVE_SIGACTION
struct sigaction **sh_old;
#else
ev_sighandler_t **sh_old;
#endif
int sh_old_max;
};
接下来可以看几个主要的函数:
evsignal_init函数主要用来初始化一些数据结构。
void
evsignal_init(struct event_base *base)
{
int i;
///创建一对流管道
if (evutil_socketpair(
AF_UNIX, SOCK_STREAM, 0, base->sig.ev_signal_pair) == -1)
event_err(1, "%s: socketpair", __func__);
///设置fd
FD_CLOSEONEXEC(base->sig.ev_signal_pair[0]);
FD_CLOSEONEXEC(base->sig.ev_signal_pair[1]);
///初始化sig数据结构
base->sig.sh_old = NULL;
base->sig.sh_old_max = 0;
base->sig.evsignal_caught = 0;
memset(&base->sig.evsigcaught, 0, sizeof(sig_atomic_t)*NSIG);
/* initialize the queues for all events */
///在libevent里面,所有的事件队列都用tail queue实现,linux下它使用的是linux自带的taile queue,具体用法可以去看man手册。
for (i = 0; i < NSIG; ++i)
TAILQ_INIT(&base->sig.evsigevents[i]);
///设置非阻塞
evutil_make_socket_nonblocking(base->sig.ev_signal_pair[0]);
///初始化event结构
event_set(&base->sig.ev_signal, base->sig.ev_signal_pair[1],
EV_READ | EV_PERSIST, evsignal_cb, &base->sig.ev_signal);
base->sig.ev_signal.ev_base = base;
base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL;
}
编缉推荐阅读以下文章
版权与免责声明
1、本站所发布的文章仅供技术交流参考,本站不主张将其做为决策的依据,浏览者可自愿选择采信与否,本站不对因采信这些信息所产生的任何问题负责。
2、本站部分文章来源于网络,其版权为原权利人所有。由于来源之故,有的文章未能获得作者姓名,署“未知”或“佚名”。对于这些文章,有知悉作者姓名的请告知本站,以便及时署名。如果作者要求删除,我们将予以删除。除此之外本站不再承担其它责任。
3、本站部分文章来源于本站原创,本站拥有所有权利。
4、如对本站发布的信息有异议,请联系我们,经本站确认后,将在三个工作日内做出修改或删除处理。
请参阅权责声明!