我們目前的網路模型大都是epoll的,因為epoll模型會比select模型效能高很多, 尤其在大連線數的情況下,作為後台開發人員需要理解其中的原因。
select/epoll的特點
select的特點:select 選擇控制代碼的時候,是遍歷所有控制代碼,也就是說控制代碼有事件響應時,select需要遍歷所有控制代碼才能獲取到哪些控制代碼有事件通知,因此效率是非常低。但是如果連線很少的情況下, select和epoll的lt觸發模式相比, 效能上差別不大。
這裡要多說一句,select支援的控制代碼數是有限制的, 同時只支援1024個,這個是控制代碼集合限制的,如果超過這個限制,很可能導致溢位,而且非常不容易發現問題, taf就出現過這個問題, 除錯了n天,才發現:)當然可以通過修改linux的socket核心調整這個引數。
epoll的特點:epoll對於控制代碼事件的選擇不是遍歷的,是事件響應的,就是控制代碼上事件來就馬上選擇出來,不需要遍歷整個控制代碼鍊錶,因此效率非常高,核心將控制代碼用紅黑樹儲存的。
對於epoll而言還有et和lt的區別,lt表示水平觸發,et表示邊緣觸發,兩者在效能以及**實現上差別也是非常大的。
epoll的lt和et的區別
lt:水平觸發,效率會低於et觸發,尤其在大併發,大流量的情況下。但是lt對**編寫要求比較低,不容易出現問題。lt模式服務編寫上的表現是:只要有資料沒有被獲取,核心就不斷通知你,因此不用擔心事件丟失的情況。
et:邊緣觸發,效率非常高,在併發,大流量的情況下,會比lt少很多epoll的系統呼叫,因此效率高。但是對程式設計要求高,需要細緻的處理每個請求,否則容易發生丟失事件的情況。
下面舉乙個列子來說明lt和et的區別(都是非阻塞模式,阻塞就不說了,效率太低):
採用lt模式下, 如果accept呼叫有返回就可以馬上建立當前這個連線了,再epoll_wait等待下次通知,和select一樣。
但是對於et而言,如果accpet呼叫有返回,除了建立當前這個連線外,不能馬上就epoll_wait還需要繼續迴圈accpet,直到返回-1,且errno==eagain,taf裡面的示例**:
if(ev.events & epollin)
else
} }while(true); }
同樣,recv/send等函式, 都需要到errno==eagain
從本質上講:與lt相比,et模型是通過減少系統呼叫來達到提高並行效率的。
epoll et詳解
et模型的邏輯:核心的讀buffer有核心態主動變化時,核心會通知你, 無需再去mod。寫事件是給使用者使用的,最開始add之後,核心都不會通知你了,你可以強制寫資料(直到eagain或者實際位元組數小於 需要寫的位元組數),當然你可以主動mod out,此時如果控制代碼可以寫了(send buffer有空間),核心就通知你。
這裡核心態主動的意思是:核心從網路接收了資料放入了讀buffer(會通知使用者in事件,即使用者可以recv資料)
並且這種通知只會通知一次,如果這次處理(recv)沒有到剛才說的兩種情況(eagin或者實際位元組數小於 需要讀寫的位元組數),則該事件會被丟棄,直到下次buffer發生變化。
與lt的差別就在這裡體現,lt在這種情況下,事件不會丟棄,而是只要讀buffer裡面有資料可以讓使用者讀,則不斷的通知你。
另外對於et而言,當然也不一定非send/recv到前面所述的結束條件才結束,使用者可以自己隨時控制,即使用者可以在自己認為合適的時候去設定in和out事件:
1 如果使用者主動epoll_mod out事件,此時只要該控制代碼可以傳送資料(傳送buffer不滿),則epoll
_wait就會響應(有時候採用該機制通知epoll_wai醒過來)。
2 如果使用者主動epoll_mod in事件,只要該控制代碼還有資料可以讀,則epoll_wait會響應。
這種邏輯在普通的服務裡面都不需要,可能在某些特殊的情況需要。 但是請注意,如果每次呼叫的時候都去epoll mod將顯著降低效率,已經吃過幾次虧了!
因此採用et寫服務框架的時候,最簡單的處理就是:
建立連線的時候epoll_add in和out事件, 後面就不需要管了
每次read/write的時候,到兩種情況下結束:
1 發生eagain
2 read/write的實際位元組數小於 需要讀寫的位元組數
對於第二點需要注意兩點:
a:如果是udp服務,處理就不完全是這樣,必須要recv到發生eagain為止,否則就丟失事件了
因為udp和tcp不同,是有邊界的,每次接收一定是乙個完整的udp包,當然recv的buffer需要至少大於乙個udp包的大小
隨便再說一下,乙個udp包到底應該多大?
對於internet,由於mtu的限制,udp包的大小不要超過576個位元組,否則容易被分包,對於公司的idc環境,建議不要超過1472,否則也比較容易分包。
b 如果傳送方傳送完資料以後,就close連線,這個時候如果recv到資料是實際位元組數小於讀寫位元組數,根據開始所述就認為到eagin了從而直接返回,等待下一次事件,這樣是有問題的,close事件丟失了!
因此如果依賴這種關閉邏輯的服務,必須接收資料到eagin為止,例如lb。
Epoll工作模式詳解
我們目前的網路模型大都是epoll的,因為epoll模型會比select模型效能高很多,尤其在大連線數的情況下,作為後台開發人員需要理解其中的原因。select epoll的特點 select的特點 select 選擇控制代碼的時候,是遍歷所有控制代碼,也就是說控制代碼有事件響應時,select需要...
EPOLL的工作模式 ET and LT
近日又繼續學習了一下epoll的工作模式,這會基本上搞清楚了,因而撰寫了此篇文件進行描述。先來一段網上的介紹文件 epoll事件分發系統可以運轉在兩種模式下 edge triggered et level triggered lt lt是預設的工作方式,並且同時支援block和no block so...
epoll的ET和LT模式詳解
從man手冊中,得到et和lt的具體描述如下 epoll事件有兩種模型 edge triggered et level triggered lt 假如有這樣乙個例子 1.我們已經把乙個用來從管道中讀取資料的檔案控制代碼 rfd 新增到epoll描述符 2.這個時候從管道的另一端被寫入了2kb的資料 ...