libevent源码分析--libevent库对信号事件的处理

信号的处理在libevent中也是一个很重要的部分,同时处理的也很巧妙,这里根据自己的理解分析其堆信号的处理。和信号相关的几个重要API都是如何调用的。

libevent源码分析--libevent库对信号事件的处理_第1张图片

这是网上关于libevent处理信号的过程图解(感谢原作者,由这个图来分析libevent如何处理信号的)

一、evsignal_init()函数(这里的分析都是按照IO复用机制的epOLL)

       这个信号初始化在epoll_init函数中,这个函数何时被调用呢,在初始化libevent实例时,event_init函数会调用这个函数,也就是在初始化全局event_base时调用,这里初始化包括三部分(一个是定时器需要使用的最小堆;一个是I/O使用的复用机制;最后一个就是信号处理机制的初始化),那么这个函数中都做了什么工作呢?

也就是上图中最上边的一个文本框的内容,创造了一个UNIX域套接字,一个用于读,一个用于写,同时初始化了event_base中和信号相关的条目,将读套接字作为event事件添加到event_base中,这一对socket可以保证在有信号到来时,可以让复用机制得到返回。

二、evsignal_add(struct event* ev)函数

      这个函数被epoll_add函数调用,但是epoll_add函数在libevent中会被哪个函数调用呢?

     这个函数会被event_add函数调用,event_add函数是libevent库中很重要的API之一。也就是想event_base中添加event实体,使用event_add函数添加event时,如果第二个参数事件不为NULL,说明是定时器事件,需要添加到最小堆中,如果第二个参数为空,可能就是I/O事件或者信号事件,如果I/O复用机制使用的是epoll系统调用,那么evsel->add函数就会调用epoll_add函数,在event_add函数中,首先判断是否为信号,如果是信号弟阿勇evsignal_add函数,然后直接返回,evsignal_add函数中都是什么内容呢/

     做一些基本的判断,如果这个信号时第一次初始化(TAILQ_EMPTY判断),然后安装信号,安装的信号处理函数都是evsignal_handler,这个信号处理函数值负责send一个字符,也即是让上面说的那个套接字得到应带,然后返回,以便处理信号事件。如果信号函数刚刚安装完成信号就发生,那么将这个信号添加到激活队列中。最后将这个信号添加到信号事件的队列中。这里注意:在evsignal_handler函数中,signal(sig,evsignal_handler),这个是安装信号函数。这句话的意思就是等到sig这个信号到来,立刻执行evsignal_handler这个函数,这个函数就是send一个字符。

三、evsignal_del()函数

      销毁某一个信号。简单的做法就是从这个信号所在的队列中删除这个信号即可。(但是还有一个_evsignal_restore_handler()函数)

四、evsignal_process()函数

       这个函数被epoll_dispatch调用,epoll_dispatch被event_dispatch函数调用,在epoll_dispatch函数中涉及到了I/O复用机制的系统调用epoll_wait,在这个函数返回后,经过判断会执行evsignal_process函数,为什么呢?

    因为和处理信号相关的一个套接字在处于epoll_wait函数监听的范围内,如果这个套接字上有可读信号,说明有信号可读,判断的一句是(base->sig.evsignal_caught),但是这个值是什么时候被更改的呢?在evsignal_handler函数内。这是一个标志位。在evsignal_process首先将这个标志位清空。for循环中就是检查信号链表,将某一个触发信号都添加到激活链表中。

      关于信号的重要函数也就这么几个,函数的调用过程也就是信号事件在libevent库中被处理的过程。

      

你可能感兴趣的:(libevent)