——事件主迴圈
張亮現在我們已經初步了解了libevent的reactor元件——event_base和事件管理框架,接下來就是libevent事件處理的中心部分——事件主迴圈,根據系統提供的事件多路分發機制執行事件迴圈,對已註冊的就緒事件,呼叫註冊事件的**函式來處理事件。
libevent將i/o事件、定時器和訊號事件處理很好的結合到了一起,本節也會介紹libevent是如何做到這一點的。
在看完本節的內容後,讀者應該會對libevent的基本框架:事件管理和主迴圈有比較清晰的認識了,並能夠把libevent的事件控制流程清晰的串通起來,剩下的就是一些細節的內容了。
libevent的事件主迴圈主要是通過event_base_loop ()函式完成的,其主要操作如下面的流程圖所示,event_base_loop所作的就是持續執行下面的迴圈。
清楚了event_base_loop所作的主要操作,就可以對比源**看個究竟了,**結構還是相當清晰的。
libevent將timer和signal事件都統一到了系統的i/o 的demultiplex機制中了,相信讀者從上面的流程和**中也能窺出一斑了,下面就再囉嗦一次了。
首先將timer事件融合到系統i/o多路復用機制中,還是相當清晰的,因為系統的i/o機制像select()和epoll_wait()都允許程式制定乙個最大等待時間(也稱為最大超時時間)timeout,即使沒有i/o事件發生,它們也保證能在timeout時間內返回。
那麼根據所有timer事件的最小超時時間來設定系統i/o的timeout時間;當系統i/o返回時,再啟用所有就緒的timer事件就可以了,這樣就能將timer事件完美的融合到系統的i/o機制中了。
這是在reactor和proactor模式(主動器模式,比如windows上的iocp)中處理timer事件的經典方法了,ace採用的也是這種方法,大家可以參考posa vol2書中的reactor模式一節。
堆是一種經典的資料結構,向堆中插入、刪除元素時間複雜度都是o(lgn),n為堆中元素的個數,而獲取最小key值(小根堆)的複雜度為o(1);因此變成了管理timer事件的絕佳人選(當然是非唯一的),libevent就是採用的堆結構。
signal是非同步事件的經典事例,將signal事件統一到系統的i/o多路復用中就不像timer事件那麼自然了,signal事件的出現對於程序來講是完全隨機的,程序不能只是測試乙個變數來判別是否發生了乙個訊號,而是必須告訴核心「在此訊號發生時,請執行如下的操作」。
如果當signal發生時,並不立即呼叫event的callback函式處理訊號,而是設法通知系統的i/o機制,讓其返回,然後再統一和i/o事件以及timer一起處理,不就可以了嘛。是的,這也是libevent中使用的方法。
問題的核心在於,當signal發生時,如何通知系統的i/o多路復用機制,這裡先買個小關子,放到訊號處理一節再詳細說明,我想讀者肯定也能想出通知的方法,比如使用pipe。
介紹了libevent的事件主迴圈,描述了libevent是如何處理就緒的i/o事件、定時器和訊號事件,以及如何將它們無縫的融合到一起。
加油!
libevent原始碼深度剖析
序幕 張亮上來當然要先誇獎啦,libevent 有幾個顯著的亮點 事件驅動 event driven 高效能 輕量級,專注於網路,不如ace那麼臃腫龐大 源 相當精煉 易讀 跨平台,支援windows linux bsd和mac os 支援多種i o多路復用技術,epoll poll dev pol...
libevent原始碼深度剖析
上來當然要先誇獎啦,libevent 有幾個顯著的亮點 事件驅動 event driven 高效能 輕量級,專注於網路,不如ace那麼臃腫龐大 源 相當精煉 易讀 跨平台,支援windows linux bsd和mac os 支援多種i o多路復用技術,epoll poll dev poll sel...
libevent原始碼深度剖析
序幕 張亮上來當然要先誇獎啦,libevent 有幾個顯著的亮點 事件驅動 event driven 高效能 輕量級,專注於網路,不如ace那麼臃腫龐大 源 相當精煉 易讀 跨平台,支援windows linux bsd和mac os 支援多種i o多路復用技術,epoll poll dev pol...