文章目录
  1. 1. signal watcher
    1. 1.1. signal watcher的配置
    2. 1.2. watcher通用接口
    3. 1.3. watcher 代码分析:
      1. 1.3.1. struct ev_signal结构体
      2. 1.3.2. signals全局变量
      3. 1.3.3. signal watcher初始化
      4. 1.3.4. signal watcher配置信号
      5. 1.3.5. signal watcher启动

signal watcher

signal watcher是需要io watcher来完成的。

  1. signalwatcher通过evpipe_init来创建管道和iowatcher(管道的fd赋值给io watcher),当收到某信号后ev_sighandler会调用并会往管道写数据。

  2. 主循环体通过backend_poll检测管道的fd可读/写时就会把对应的io watcher放到loop->pending上。

  3. 主循环体调用ev_invoke_pending就会检测pending上就绪的io
    watcher并调用该watcher的回调函数pipecb(pipecb函数就会读取管道数据,并把signal watcher放到loop->pengding上),然后ev_invoke_pending检测到signal watcher被激活,调用它的回调函数signal_do。

signal watcher的配置

evinit(事件)—>ev事件set()—>ev事件_start()

测试用例:我创建一个信号事件,当接收到SIGINT信号时回调signal_do函数。

ev_singal signal_e;

void signal_do(struct ev_loop *loop, ev_sinal *signal_e, int e)
{
    printf("signal callback!\n");
    ev_signal_stop(loop, signal_e);
}

int main(int argc ,char *argv[])
{
    struct ev_loop *loop = ev_default_loop(0);

    ev_singal signal_e;
    ev_init(&signal_e,signal_do);
    ev_signal_set(&signal_e,SIGINT); 
    ev_signal_start(loop,&signal_e);

    ev_run(loop,0);

    return 0;
}

watcher通用接口

typedef void (*)(struct ev_loop *loop, ev_TYPE *watcher, int revents) callback; // callback都是这种类型
ev_init (ev_TYPE *watcher, callback); // 初始化watcher
ev_TYPE_set (ev_TYPE *watcher, [args]); // 设置watcher
ev_TYPE_init (ev_TYPE *watcher, callback, [args]); // 通常使用这个函数最方便,初始化和设置都在这里
ev_TYPE_start (loop, ev_TYPE *watcher); // 注册watcher
ev_TYPE_stop (loop, ev_TYPE *watcher); // 注销watcher
ev_set_priority (ev_TYPE *watcher, int priority); // 设置优先级
ev_feed_event (loop, ev_TYPE *watcher, int revents); // 这个做跨线程通知非常有用,相当于触发了某个事件。
bool ev_is_active (ev_TYPE *watcher); // watcher是否active.
bool ev_is_pending (ev_TYPE *watcher); // watcher是否pending.
int ev_clear_pending (loop, ev_TYPE *watcher); // 清除watcher pending状态并且返回事件

watcher 代码分析:

struct ev_signal结构体

typedef struct ev_signal
{
  EV_WATCHER_LIST (ev_signal)
  int signum; /* ro */
} ev_signal;

libev里面很多都是宏声明结构体和函数,下面就是struct ev_signal里宏被展开后的形式:

typedef struct ev_signal
{
    /* active表示事件是否被激活 */
    int active;
    /* pending表示事件就绪,等待处理 */
    int pending; 
    /* priority当前事件优先级 */
    int priority;
    /* data附件数据指针,用来在时间中携带额外的数据 */
    void *data;
    /* cb是事件触发后的回调函数 */
    void (*cb)(EV_P_ struct type *w, int revents);
    struct ev_watcher_list *next;
    int signum; /* ro */
} ev_signal;

signals全局变量

所有SIGINT watcher都挂载到signals[SIGINT-1].head上。

typedef struct
{
    EV_ATOMIC_T pending; /* 信号事件是否激活 */ 
    struct ev_loop *loop;
    WL head;
} ANSIG;

static ANSIG signals [EV_NSIG - 1];

signal watcher初始化

ev_init(&signal_e, signal_do);

#define ev_init(ev,cb_) do {            \
    ((ev_watcher *)(void *)(ev))->active  =    \
    ((ev_watcher *)(void *)(ev))->pending = 0;    \
    ev_set_priority ((ev), 0);            \
    ev_set_cb ((ev), cb_);            \
} while (0)

signal watcher配置信号

ev_signal_set(&signal_e,SIGINT)
#define ev_signal_set(ev,signum_)            do { (ev)->signum = (signum_); } while (0);

signal watcher启动

ev_signal_start(loop,&signal_e);

void noinline
ev_signal_start (struct ev_loop *loop,  ev_signal *w) EV_THROW
{
    if (expect_false (ev_is_active (w)))
        return;

    signals [w->signum - 1].loop = loop;
    /* # define EV_FREQUENT_CHECK ev_verify (EV_A)
     * 调用ev_verify(loop)
     */
    EV_FREQUENT_CHECK;

    /* 此时loop->sigfd == -1 */
    if (loop->sigfd == -2)
    {
        /* 创建一个fd来接受信号
         * 把信号集loop->sigfd_set与fd关联起来
         * 第一个参数为-1表示新建一个signalfd
         */
        loop->sigfd = signalfd (-1, &sigfd_set, SFD_NONBLOCK | SFD_CLOEXEC);
        if (loop->sigfd < 0 && errno == EINVAL)
            loop->sigfd = signalfd (-1, &sigfd_set, 0); /* retry without flags */

        if (loop->sigfd >= 0)
        {
            fd_intern (loop->sigfd); /* doing it twice will not hurt */
            sigemptyset (&loop->sigfd_set);
            ev_io_init (&loop->sigfd_w, sigfdcb, sigfd, EV_READ);
            ev_set_priority (&loop->sigfd_w, EV_MAXPRI);
            ev_io_start (loop, &loop->sigfd_w);
            ev_unref (loop); /* signalfd watcher should not keep loop alive */
        }
    }

    /* 此时loop->sigfd == -1 */
    if (loop->sigfd >= 0)
    {
        /* TODO: check .head */
        sigaddset (&loop->sigfd_set, w->signum);
        sigprocmask (SIG_BLOCK, &loop->sigfd_set, 0);
        signalfd (loop->sigfd, &sigfd_set, 0);
    }

    /* 
     * typedef ev_watcher *W  
     * 调整water的优先级
     * 激活watcher, w->active = 1
     * loop->activecnt++
     */
    ev_start (loop, (W)w, 1);

把SIGINT信号的 watcher挂到signals[SIGINT-1]链表上

    wlist_add (&signals [w->signum - 1].head, (WL)w);

    if (!((WL)w)->next)
        /* 此时loop->sigfd == -1 */
        if (loop->sigfd < 0) /*TODO*/
        {
            struct sigaction sa;

ev_pipe_init:

1.建立管道(loop->evpipe), 把管道信息赋值给一个io
watcher(loop->pipe_w)。

            evpipe_init (loop);

ev_sighandler的作用当接受SIGINT信号时,调用evpipe_write函数触发以下事件:

  1. watcher设置为就绪状态(loop->sig_pending设置为1)。

  2. 往管道写信息(主循环体会调用io

     watcher(loop->pipe_w)回调函数pipecb来读取管道信息,若signal
     watcher已激活(sig_pending等于1),主循环下一步就会调用测试代码的注册回调函数signal_do)。
    
             sa.sa_handler = ev_sighandler;
             sigfillset (&sa.sa_mask);
             /* if restarting works we save one iteration */
             sa.sa_flags = SA_RESTART;
             sigaction (w->signum, &sa, 0);
    
             if (loop->origflags & EVFLAG_NOSIGMASK)
             {
                 sigemptyset (&sa.sa_mask);
                 sigaddset (&sa.sa_mask, w->signum);
                 sigprocmask (SIG_UNBLOCK, &sa.sa_mask, 0);
             }
         }
    
     EV_FREQUENT_CHECK;
    

    }