zoukankan      html  css  js  c++  java
  • 浅析libev的ev_signal过程

      ev_signal是libev提供的对信号处理的一个模块,基本上是对sigaction函数的一个封装,并将本身是异步的信号转化为同步。ev_signal的使用十分简单:

    #include <ev.h>
    #include <stdio.h>
    
    static void
       sigint_cb (struct ev_loop *loop, ev_signal *w, int revents)
       {
           puts ( "signal ....." );
       }
    
    int main(int argc,char* argv[])
    {
        struct ev_loop *loop = EV_DEFAULT;
    
       ev_signal signal_watcher;
       ev_signal_init (&signal_watcher, sigint_cb, SIGINT);
       ev_signal_start (loop, &signal_watcher);
    
       ev_run (loop,0);
    
        return 0;
    }

    C++的用法:

    #include <iostream>
    
    #include <ev++.h>
    #include <signal.h>
    
    class CSignal
    {
    public:
        void sig_cb(  ev::sig  &w, int revents )
        {
            std::cout << "catch signal ..." << std::endl;
        }
    };
    
    int main()
    {
        CSignal sg;
    
        ev::sig sig_watcher;
        sig_watcher.set<CSignal,&CSignal::sig_cb>( &sg );
    
        sig_watcher.start(SIGINT);
    
        ev_run( EV_DEFAULT,0 );
    }

      然后我们来看一下libev内部处理信号的大概流程:

    1.libev有各种各样的watch,包括io、signal、timer,但这些watch基本使用以下结构

    typedef struct ev_watcher {
        int active;
        int pending;
        int priority;
        void *data;
        void (*cb)(struct ev_loop *loop, struct ev_watcher *w, int revents);
    } ev_watcher;

    2.libev定义了一个全局变量EV_DEFAULT,通过ev_default_loop (0)返回一个指针。其实ev_default_loop是在维护一个全局变量static struct ev_loop default_loop_struct当第一次调用ev_default_loop会初始化default_loop_struct,以后都只是返回它的指针了。这个全局变量自己在维护了所有的watcher。并在一个loop中检测它们是否触发事件。

    3.当创建一个ev::sig对象,就创建了一个ev_watcher对象,并通过set函数设置对象指针,回调函数到对象里的data、cb变量,C方式则是通过ev_signal_init、ev_signal_set这些函数来设置。然后把这个watcher交给EV_DEFAULT管理。

    4.当调用ev_signal_start函数,会调用signalfd为当前信号创建一个文件描述符,然后通过ev_io来监控该文件的读事件。如果signalfd失败,调用evpipe_init创建一个pipe,注册一个ev_io到epoll中。调用原生的sigaction函数,将回调函数处理为ev_sighandler,收到信号时在ev_sighandler中调用ev_feed_signal来往pipe中写数据。这样在一个loop中,原先的ev_watcher对象就会收到读消息。

      可见,对于大多数使用了libev作为eventloop的程序而言,这样应该是足够简洁方便的。更重要的是,libev有一层C++的wrap,使得在使用C++构建的程序能更方便的调用类的成员函数,而原生的sigaction是不能注册类成员函数为回调函数的。但相对原生的sigaction而言,libev有一个致命的地方:必须要在事件循环中才能收到信号,即ev_run之后。想想,比如你的程序在初始化进入loop之前的时候当掉了,如果这时你想通过捕捉信号来做一些清理工作,libev办不到,sigaction则OK。

  • 相关阅读:
    Git之不明觉厉11-利其器source tree
    GUI for git|SourceTree|入门基础
    UIButton
    NSDictionary
    注释方法、代码块加快捷键注释
    UIActionSheet
    UIActivityIndicatorView
    UIPickerView
    UIImageView
    UIAlertView
  • 原文地址:https://www.cnblogs.com/coding-my-life/p/4220128.html
Copyright © 2011-2022 走看看