【c++】26.浅谈“事件驱动”、select、poll、epoll
淺談“事件驅動”
1.通常,我們設計一個事件處理模型的程序有兩種思路:
- 一種是通過輪詢的方式;
- 一種通過事件驅動的方式,事件驅動方式也被稱為消息通知方式。
下面舉個簡單收信的例子,來說明兩種實現方式的不同:
- (1) 傳統的郵件,郵遞員把它放到你家的郵箱里。因為你不知道什么時候有郵件,所以你要經常去檢查郵箱,最近到底有沒有郵件。這就是所謂的輪詢方式,你要時常去檢查,有沒有發生事件發生,當你檢查到有事件發生時,你采取相應措施,處理相關事件。
- (2)現代的電子郵件,你不用自己去查看郵箱,如果有新郵件,電腦會給你發消息,提示你有新郵件,然后你去查看郵箱。這就是所謂的事件驅動(消息通知),你不用去關心事件什么時候發生,當有事件發生時,會有人通知你,事件發生了,然后你再采取相應的措施,處理相關事件。
通過上面的例子,可以看出,輪詢的最大的弊端在于,你要做許多無謂的檢查,具體到程序中,就是會有CPU資源的浪費,換言之,就是CPU利用率不高。而事件驅動,就很好的解決了這個問題。不過事件驅動的缺點在于,模型較為復雜,程序寫起來會比較復雜,但是,一旦掌握了事件驅動這種模型的基本設計思路,必定能達到事半功倍的效果。
2.網絡服務器設計過程中用到的 事件驅動模型
在這里我要說一說,通常的網絡服務器設計過程中的事件驅動模型,希望能對需要幫助的朋友一點小小的幫助,這將是我很樂意看到的。
通常,高吞吐、大并發的網絡服務器,都會采用事件驅動模型,其優點就是CPU利用率高,寫出來的程序效率比較高。
通常,我們會用select/poll/epoll,這些由系統提供的I/O復用的API來實現事件驅動模型。
網絡程序中的事件,通常可以分為三類:
- 一類是可讀事件(數據已到達內核,上層應用可以調用相關讀接口進行數據讀取);
- 一類是可寫事件(內核的寫緩沖區有空余,上層應用可以調用相關寫接口進行數據寫入);
- 一類是異常(或出錯)事件(發生了異常情況,需要進行異常處理)。
select和poll, 與epoll相比,當并發數比較大的時候,性能差別會比較大,主要是因為內核通知事件的方式不同。
-
在select和poll中,內核只是在通知有多少個fd上發生了事件,并在相應的fd上做了標記,上層應用要想知道具體是那個fd上發生了什么事件,就必須去遍歷整個fd的集合。
-
而在epoll中,操作系統通知事件的方式是,把有事件發生的fd集合返回給上層應用,這樣就不需要再去做無謂的遍歷了。尤其在并發數比較大(fd集合中fd個數多)的時候,它們之間的性能差別還是挺大的。因此,性能要求比較高的網絡服務器的實現,大多都使用epoll。
下圖所示是一種比較常見的事件驅動(消息通知)模型的簡單實現:
上圖中,EventMonitor是用來從操作系統獲取事件的線程,EventProcessor是實際來處理事件的線程。
在EventMonitor中調用select/poll/epoll_wait來獲取事件,然后把發生的事件,以消息的方式通知給EventProcessor,EventProcessor收到消息后,處理所發生的事件。
這里EventProcessor可以有多個,同一個fd的上事件,一般在同一個EventProcessor上處理。這樣,EventMonitor的工作就是獲取事件,是比較輕量級的,重量級的運算處理工作都由EventProcessor來處理,通過調整EventProcessor的個數,提高CPU的利用效率,從而提高整個程序的性能。
總結
以上是生活随笔為你收集整理的【c++】26.浅谈“事件驱动”、select、poll、epoll的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【c++】24.std::functio
- 下一篇: s3c2440移植MQTT