libevent源码深度剖析八
libevent源碼深度剖析八
——集成信號處理
張亮
????? 現在我們已經了解了libevent的基本框架:事件管理框架和事件主循環。上節提到了libevent中I/O事件和Signal以及Timer事件的集成,這一節將分析如何將Signal集成到事件主循環的框架中。
1 集成策略——使用socket pair
?? ?? 前一節已經做了足夠多的介紹了,基本方法就是采用“消息機制”。在libevent中這是通過socket pair完成的,下面就來詳細分析一下。
????? Socket pair就是一個socket對,包含兩個socket,一個讀socket,一個寫socket。工作方式如下圖所示:
???????????????????????????????
??? 創建一個socket pair并不是復雜的操作,可以參見下面的流程圖,清晰起見,其中忽略了一些錯誤處理和檢查。
???????????????????????????
? ? ? ? ? ? ??
Libevent提供了輔助函數evutil_socketpair()來創建一個socket pair,可以結合上面的創建流程來分析該函數。
2 集成到事件主循環——通知event_base
?? ?? Socket pair創建好了,可是libevent的事件主循環還是不知道Signal是否發生了啊,看來我們還差了最后一步,那就是:為socket pair的讀socket在libevent的event_base實例上注冊一個persist的讀事件。
??? ? 這樣當向寫socket寫入數據時,讀socket就會得到通知,觸發讀事件,從而event_base就能相應的得到通知了。
前面提到過,Libevent會在事件主循環中檢查標記,來確定是否有觸發的signal,如果標記被設置就處理這些signal,這段代碼在各個具體的I/O機制中,以Epoll為例,在epoll_dispatch()函數中,代碼片段如下:
完整的處理框架如下所示:
??? ? ? ?
注1:libevent中,初始化階段并不注冊讀socket的讀事件,而是在注冊信號階段才會測試并注冊;
注2:libevent中,檢查I/O事件是在各系統I/O機制的dispatch()函數中完成的,該dispatch()函數在event_base_loop()函數中被調用;
3 evsignal_info結構體
????? Libevent中Signal事件的管理是通過結構體evsignal_info完成的,結構體位于evsignal.h文件中,定義如下:
下面詳細介紹一下個字段的含義和作用:
1)ev_signal, 為socket pair的讀socket向event_base注冊讀事件時使用的event結構體;
2)ev_signal_pair,socket pair對,作用見第一節的介紹;
3)ev_signal_added,記錄ev_signal事件是否已經注冊了;
4)evsignal_caught,是否有信號發生的標記;是volatile類型,因為它會在另外的線程中被修改;
5)evsigvents[NSIG],數組,evsigevents[signo]表示注冊到信號signo的事件鏈表;
6)evsigcaught[NSIG],具體記錄每個信號觸發的次數,evsigcaught[signo]是記錄信號signo被觸發的次數;
7)sh_old記錄了原來的signal處理函數指針,當信號signo注冊的event被清空時,需要重新設置其處理函數;
??? evsignal_info的初始化包括,創建socket pair,設置ev_signal事件(但并沒有注冊,而是等到有信號注冊時才檢查并注冊),并將所有標記置零,初始化信號的注冊事件鏈表指針等。
4 注冊、注銷signal事件
????? 注冊signal事件是通過evsignal_add(struct event *ev)函數完成的,libevent對所有的信號注冊同一個處理函數evsignal_handler(),該函數將在下一段介紹,注冊過程如下:
1 取得ev要注冊到的信號signo;
2 如果信號signo未被注冊,那么就為signo注冊信號處理函數evsignal_handler();
3 如果事件ev_signal還沒喲注冊,就注冊ev_signal事件;
4 將事件ev添加到signo的event鏈表中;
從signo上注銷一個已注冊的signal事件就更簡單了,直接從其已注冊事件的鏈表中移除即可。如果事件鏈表已空,那么就恢復舊的處理函數;
下面的講解都以signal()函數為例,sigaction()函數的處理和signal()相似。
處理函數evsignal_handler()函數做的事情很簡單,就是記錄信號的發生次數,并通知event_base有信號觸發,需要處理:
5 小節
本節介紹了libevent對signal事件的具體處理框架,包括事件注冊、刪除和socket pair通知機制,以及是如何將Signal事件集成到事件主循環之中的。
總結
以上是生活随笔為你收集整理的libevent源码深度剖析八的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 处理大并发之四 libevent dem
- 下一篇: 结构体与位域的对齐