淺析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。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM