天天看點

<心跳連接配接一>關于信号有關的APUE和SIGALRM信号執行個體 1 信号基本原理和函數接口2 SIGALRM信号執行個體----心跳連接配接

1 信号基本原理和函數接口

(1)APUE一書中第10章信号

該章節詳細講解了unix系統信号相關的内容,下面這篇文章很好的總結了本章的知識概要,

原文連結:http://blog.csdn.net/atfield/article/details/1532506

每小節知識執行個體參見《APUE》第十章p233~285.

(2)信号的“未決”和“阻塞”

原文連結:http://blog.csdn.net/sunyubo458/article/details/4484957

“未決”:信号的狀态,從信号産生到信号被處理的一段時間;

“阻塞”:阻塞的是信号的處理,不阻塞信号的産生。

信号的阻塞和回複可通過sigprocmask()接口實作。在信号阻塞到回複的期間,是信号的未決狀态。

信号經過産生--注冊--登出--處理的四個階段為信号的生命周期。

實時信号(可靠信号):每産生一個就向task_struct結構中注冊一個sigquene結構體,登出的時候根據同一信号的注冊個數進行不同處理,釋放sigquene結構體,且(隻有一個,則直接在未決信号集中删除;有多個,則不删除)。

非實時信号(不可靠信号):每産生一個就向task_struct結構中注冊一個sigquene結構體,登出的時候根據同一信号的注冊個數進行不同處理,釋放sigquene結構體,在未決信号集中删除該信号。

2 SIGALRM信号執行個體----心跳連接配接

(1)執行個體背景

在實作心跳連接配接時,使用的是setitimer()的定時器函數,定時器守護線程每一段時間發送一個SIGALRM信号,主線程收到此信号進行處理,向對方發送一個心跳封包包,感覺和對方網絡連接配接的狀況(網絡線路故障,對方機器當機等不正常關閉連接配接的情況)。

(2)關鍵結構TimerManager

對多并發的連接配接的處理采用的是EPOLL架構,線程間用管道Pipe進行的通信。系統構造一個全局的定時器管理類對象TimerManager(g_TimerManager),擁有pipe(接收各線程的Timer),pipe[0]讀端綁定為RecvData()-->RecvTimer()的讀端。在init()時,屏蔽SIGALRM信号,建立定時器線程,線程函數用pthread_procmask()恢複信号,設定定時時間(每一秒鐘查詢m_TimerList中的時鐘是否過期)

struct itimerval { 
                struct timerval it_interval; 
                struct timerval it_value; 
              }; 
 struct timeval { 
                long tv_sec; 
                long tv_usec; 
              };            
           

注釋:it_interval為每經過it_intercal時間久發送一個SIGALRM信号;it_value為經過該段時間就發送SIGALRM信号(隻發一次)。

信号SIGALRM處理函數為TimerManager.CheckTimeOut()。

        需要定時的時候,初始化對象Timer,調用attachTimer()----->registerThread(),将Timer注冊到TimerManager的m_TimerList中,綁定讀端和寫端到全局Epoll中,将Timer對象包裝寫入m_MsgPipe[1]中。

       線程函數功能:恢複SIGALRM後,死循環從m_MsgPipe[0]讀取TImer Obj,将Timer Obj insert()進TimerList中,再做checkTimeOut()檢查時鐘逾時。

      TimerManager維護的成員有:

int        m_MsgPipe1[2];            //for TimerManager receiving Timers from main thread

    EpollEvent m_EpollEvent;             //EpollEvent Handler
    std::map<pthread_t,int> m_MsgRPipeList;   //綁定的Timer的Epoll的讀端
    std::map<pthread_t,int> m_MsgWPipeList;   //綁定的Timer的Epoll的寫端
    std::multiset<Timer*,LessTimer> m_TimerList;  // 管理的多線程多個定時器連結清單
           

      CheckTimeOut():将到時的定時器SendTimer(Timer* P)到TimerManager的m_MsgWPipeList[p->getTid()],觸發主線程Epoll的可讀事件,m_MsgRPipeList[p->getTid()],調用RecvData(),取出Timer *P,調用p->DoAction(),實作定時發送心跳封包包的任務。

注釋:1 文中的TimerManage和Epollr源代碼可Pm我獲得。

            2 代碼中設計多重集合的排序,Timer的優先級包裝,與本文探讨的定時器信号關系不大,暫不詳解。

繼續閱讀