epoll

epoll

計算機術語
epoll是Linux内核為處理大批量文件描述符而作了改進的poll,是Linux下多路複用IO接口select/poll的增強版本,它能顯着提高程序在大量并發連接中隻有少量活躍的情況下的系統CPU利用率。另一點原因就是獲取事件的時候,它無須遍曆整個被偵聽的描述符集,隻要遍曆那些被内核IO事件異步喚醒而加入Ready隊列的描述符集合就行了。epoll除了提供select/poll那種IO事件的水平觸發(Level Triggered)外,還提供了邊緣觸發(Edge Triggered),這就使得用戶空間程序有可能緩存IO狀态,減少epoll_wait/epoll_pwait的調用,提高應用程序效率。[1]
    中文名: 外文名:epoll 所屬學科: 優點:内核微調等 工作方式:LT和ET 系統調用:epoll_create, epoll_ctl等

優點

支持一個進程打開大數目的socket描述符

select最不能忍受的是一個進程所打開的FD是有一定限制的,由FD_SETSIZE設置,默認值是1024。對于那些需要支持的上萬連接數目的IM服務器來說顯然太少了。這時候你一是可以選擇修改這個宏然後重新編譯内核,不過資料也同時指出這樣會帶來網絡效率的下降,二是可以選擇多進程的解決方案(傳統的Apache方案),不過雖然linux上面創建進程的代價比較小,但仍舊是不可忽視的,加上進程間數據同步遠比不上線程間同步的高效,所以也不是一種完美的方案。

不過epoll則沒有這個限制,它所支持的FD上限是最大可以打開文件的數目,這個數字一般遠大于2048,舉個例子,在1GB内存的機器上大約是10萬左右,具體數目可以cat/proc/sys/fs/file-max查看,一般來說這個數目和系統内存關系很大。

IO效率不随FD數目增加而線性下降

傳統的select/poll另一個緻命弱點就是當你擁有一個很大的socket集合,不過由于網絡延時,任一時間隻有部分的socket是“活躍”的,但是select/poll每次調用都會線性掃描全部的集合,導緻效率呈現線性下降。但是epoll不存在這個問題,它隻會對“活躍”的socket進行操作---這是因為在内核實現中epoll是根據每個fd上面的callback函數實現的。那麼,隻有“活躍”的socket才會主動的去調用callback函數,其他idle狀态socket則不會,在這點上,epoll實現了一個“僞”AIO,因為這時候推動力在os内核。

在一些benchmark中,如果所有的socket基本上都是活躍的---比如一個高速LAN環境,epoll并不比select/poll有什麼效率,相反,如果過多使用epoll_ctl,效率相比還有稍微的下降。但是一旦使用idle connections模拟WAN環境,epoll的效率就遠在select/poll之上了。

使用mmap加速内核與用戶空間的消息傳遞

這點實際上涉及到epoll的具體實現了。無論是select,poll還是epoll都需要内核把FD消息通知給用戶空間,如何避免不必要的内存拷貝就很重要,在這點上,epoll是通過内核與用戶空間mmap同一塊内存實現的。而如果你像我一樣從2.5内核就關注epoll的話,一定不會忘記手工mmap這一步的。

内核微調

這一點其實不算epoll的優點了,而是整個linux平台的優點。也許你可以懷疑linux平台,但是你無法回避linux平台賦予你微調内核的能力。比如,内核TCP/IP協議棧使用内存池管理sk_buff結構,那麼可以在運行時期動态調整這個内存pool(skb_head_pool)的大小---通過echoXXXX>/proc/sys/net/core/hot_list_length完成。再比如listen函數的第2個參數(TCP完成3次握手的數據包隊列長度),也可以根據你平台内存大小動态調整。更甚至在一個數據包面數目巨大但同時每個數據包本身大小卻很小的特殊系統上嘗試最新的NAPI網卡驅動架構。

使用

令人高興的是,2.6内核的epoll比其2.5開發版本的/dev/epoll簡潔了許多,所以,大部分情況下,強大的東西往往是簡單的。唯一有點麻煩是epoll有2種工作方式:LT和ET。

LT(level triggered)是缺省的工作方式,并且同時支持block和no-block socket.在這種做法中,内核告訴你一個文件描述符是否就緒了,然後你可以對這個就緒的fd進行IO操作。如果你不作任何操作,内核還是會繼續通知你的,所以,這種模式編程出錯誤可能性要小一點。傳統的select/poll都是這種模型的代表。

ET(edge-triggered)是高速工作方式,隻支持no-block socket。在這種模式下,當描述符從未就緒變為就緒時,内核通過epoll告訴你。然後它會假設你知道文件描述符已經就緒,并且不會再為那個文件描述符發送更多的就緒通知,直到你做了某些操作導緻那個文件描述符不再為就緒狀态了(比如,你在發送,接收或者接收請求,或者發送接收的數據少于一定量時導緻了一個EWOULDBLOCK 錯誤)。但是請注意,如果一直不對這個fd作IO操作(從而導緻它再次變成未就緒),内核不會發送更多的通知(only once),不過在TCP協議中,ET模式的加速效用仍需要更多的benchmark确認。

ET和LT的區别就在這裡體現,LT事件不會丢棄,而是隻要讀buffer裡面有數據可以讓用戶讀,則不斷的通知你。而ET則隻在事件發生之時通知。可以簡單理解為LT是水平觸發,而ET則為邊緣觸發。LT模式隻要有事件未處理就會觸發,而ET則隻在高低電平變換時(即狀态從1到0或者0到1)觸發。

上一篇:腿毛

下一篇:桌遊吧

相關詞條

相關搜索

其它詞條