天天看點

Linux Epoll介紹和程式執行個體

1. epoll 是何方神聖?

epoll 可是目前在 linux 下開發大規模并發網絡程式的熱門人選, epoll 在 linux2.6 核心中正式引入,和 select 相似,其實都 i/o 多路複用技術而已 ,并沒有什麼神秘的。

其實在 linux 下設計并發網絡程式,向來不缺少方法,比如典型的 apache 模型( process per connection ,簡稱 ppc ), tpc ( thread per connection )模型,以及 select 模型和 poll 模型,那為何還要再引入 epoll 這個東東呢?那還是有得說說的 …

2. 常用模型的缺點

如果不擺出來其他模型的缺點,怎麼能對比出 epoll 的優點呢。

2.1 ppc/tpc 模型

這兩種模型思想類似,就是讓每一個到來的連接配接一邊自己做事去,别再來煩我 。隻是 ppc 是為它開了一個程序,而 tpc 開了一個線程。可是别煩我是有代價的,它要時間和空間啊,連接配接多了之後,那麼多的程序 / 線程切換,這開銷就上來了;是以這類模型能接受的最大連接配接數都不會高,一般在幾百個左右。

2.2 select 模型

1. 最大并發數限制,因為一個程序所打開的 fd (檔案描述符)是有限制的,由 fd_setsize 設定,預設值是 1024/2048 ,是以 select 模型的最大并發數就被相應限制了。自己改改這個 fd_setsize ?想法雖好,可是先看看下面吧 …

2. 效率問題, select 每次調用都會線性掃描全部的 fd 集合,這樣效率就會呈現線性下降,把 fd_setsize 改大的後果就是,大家都慢慢來,什麼?都逾時了??!!

3. 核心 / 使用者空間 記憶體拷貝問題,如何讓核心把 fd 消息通知給使用者空間呢?在這個問題上 select 采取了記憶體拷貝方法。

2.3 poll 模型

基本上效率和 select 是相同的, select 缺點的 2 和 3 它都沒有改掉。

3. epoll 的提升

把其他模型逐個批判了一下,再來看看 epoll 的改進之處吧,其實把 select 的缺點反過來那就是 epoll 的優點了。

3.1. epoll 沒有最大并發連接配接的限制,上限是最大可以打開檔案的數目,這個數字一般遠大于 2048, 一般來說這個數目和系統記憶體關系很大 ,具體數目可以 cat /proc/sys/fs/file-max 察看。

3.2. 效率提升, epoll 最大的優點就在于它隻管你“活躍”的連接配接 ,而跟連接配接總數無關,是以在實際的網絡環境中, epoll 的效率就會遠遠高于 select 和 poll 。

3.3. 記憶體拷貝, epoll 在這點上使用了“共享記憶體 ”,這個記憶體拷貝也省略了。

4. epoll 為什麼高效

epoll 的高效和其資料結構的設計是密不可分的,這個下面就會提到。

首先回憶一下 select 模型,當有 i/o 事件到來時, select 通知應用程式有事件到了快去處理,而應用程式必須輪詢所有的 fd 集合,測試每個 fd 是否有事件發生,并處理事件;代碼像下面這樣:

epoll 不僅會告訴應用程式有i/0 事件到來,還會告訴應用程式相關的資訊,這些資訊是應用程式填充的,是以根據這些資訊應用程式就能直接定位到事件,而不必周遊整個fd 集合。

5. epoll 關鍵資料結構

前面提到 epoll 速度快和其資料結構密不可分,其關鍵資料結構就是:

可見 epoll_data 是一個 union 結構體 , 借助于它應用程式可以儲存很多類型的資訊 :fd 、指針等等。有了它,應用程式就可以直接定位目标了。

6. 使用 epoll

既然 epoll 相比 select 這麼好,那麼用起來如何呢?會不會很繁瑣啊 … 先看看下面的三個函數吧,就知道 epoll 的易用了。

生成一個 epoll 專用的檔案描述符,其實是申請一個核心空間,用來存放你想關注的 socket fd 上是否發生以及發生了什麼事件。 size 就是你在這個 epoll fd 上能關注的最大 socket fd 數,大小自定,隻要記憶體足夠。

控制某個 epoll 檔案描述符上的事件:注冊、修改、删除。其中參數 epfd 是 epoll_create() 建立 epoll 專用的檔案描述符。相對于 select 模型中的 fd_set 和 fd_clr 宏。

等待 i/o 事件的發生;參數說明:

epfd: 由 epoll_create() 生成的 epoll 專用的檔案描述符;

epoll_event: 用于回傳代處理事件的數組;

maxevents: 每次能處理的事件數;

timeout: 等待 i/o 事件發生的逾時值;

傳回發生事件數。

相對于 select 模型中的 select 函數。

7. 例子程式

下面是一個簡單 echo server 的例子程式,麻雀雖小,五髒俱全,還包含了一個簡單的逾時檢查機制,簡潔起見沒有做錯誤處理。

原文位址:http://blog.csdn.net/sparkliang/article/details/4770655

繼續閱讀