條件觸發和邊緣觸發 及 epoll 的優點

2021-06-29 04:36:28 字數 2881 閱讀 3565

舉個讀socket的例子,假定經過長時間的沉默後,現在來了100個位元組,這時無論邊緣觸發和條件觸發都會產生乙個read ready notification通知應用程式可讀。應用程式讀了50個位元組,然後重新呼叫api等待io事件。

這時條件觸發的api會因為還有50個位元組可讀從而立即返回使用者乙個read ready notification。而邊緣觸發的api因為可讀這個狀態沒有發生變化而陷入長期等待

因此在使用邊緣觸發的api時,要注意每次都要讀到socket返回ewouldblock為止,否則這個socket就算廢了。而使用條件觸發的api時,如果應用程式不需要寫就不要關注socket可寫的事件,否則就會無限次的立即返回乙個write ready notification。大家常用的select就是屬於條件觸發這一類,長期關注socket寫事件會出現cpu100%的毛病。

支援乙個程序開啟大數目的socket描述符(fd)

select最不能忍受的是乙個程序所開啟的fd是有一定限制的,由fd_setsize設定,預設值是2048。對於那些需要支援的上萬連線數目的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)的大小 — 通過echo ***x>/proc/sys/net/core/hot_list_length完成。再比如listen函式的第2個引數(tcp完成3次握手 的資料報佇列長度),也可以根據你平台記憶體大小動態調整。更甚至在乙個資料報數目巨大但同時每個資料報本身大小卻很小的特殊系統上嘗試最新的napi網絡卡驅動架構。 

epoll的 LT 條件觸發和 ET 邊緣觸發

下面是二者的定義 條件觸發 lt 只要輸入緩衝有資料就會一直通知該事件 邊緣觸發 et 輸入緩衝收到資料時僅註冊1次該事件,即使輸入緩衝中還留有資料,也不會再進行註冊 從而我要說明的是,為什麼要強調邊緣觸發要使用非阻塞io 因為在伺服器端當epoll wait監聽到有客戶端fd可讀寫時,那麼就只會返...

epoll 水平觸發 邊緣觸發

水平觸發 只要緩衝區還有資料,核心就還會通知使用者。使用者如果第一次讀取資料沒讀完,即使沒有任何新的操作觸發,還是可以繼續通過epoll wait來獲取事件 邊緣觸發 只有當新事件觸發的時候,才能通過epoll wait來獲取資料,如果第一次讀取資料沒讀完,就只能等待下一次事件觸發來獲取餘下的資料。...

epoll 水平觸發 邊緣觸發

先簡單比較一下level trigger 和 edge trigger 模式的不同。讓我們換乙個角度來理解et模式,事實上,epoll的et模式其實就是socket io完全狀態機。當socket由不可讀變成可讀時,epoll的et模式返回read 事件。對於read 事件,開發者需要保證把讀取緩衝...