前面的兩篇部落格我們已經為大家介紹了select和poll函式,但是在學習中我們發現select和poll存在效率上的問題。而今天的主角epoll函式真的是讓人驚豔的設計,它是在2.5.44核心中被引進的,它幾乎具備了之前所說的一切優點,被公認為linux2.6下效能最好的多路i/o就緒通知方法。包括現在最火的nginx伺服器底層使用的也是epoll多路轉接
int
epoll_create
(int size)
;
引數是乙個int型別的整數,這個數字隨便填,在2.6以後就被忽略了相當於是乙個歷史遺留問題。這裡的返回值比較重要,epoll返回乙個控制代碼,這個控制代碼能幫我們找到之後要使用的所有epoll機制。
int
epoll_ctl
(int epfd,
int op,
int fd,
struct epoll_event *event)
;
引數介紹: 事件
描述epollin
表示對應的檔案描述符可以讀 (包括對端socket正常關閉);
epollout
表示對應的檔案描述符可以寫
epollpri
表示對應的檔案描述符有緊急的資料可讀 (這裡應該表示有帶外資料到來)
epollerr
表示對應的檔案描述符發生錯誤(預設被關心)
epollhup
表示對應的檔案描述符被結束通話(預設被關心)
epollet
將epoll設為邊緣觸發(edge triggered)模式, 這是相對於水平觸發(level triggered)來說的
epolloneshot
只監聽一次事件, 當監聽完這次事件之後, 如果還需要繼續監聽這個socket的話, 需要再次把這個socket加入到epoll佇列裡.
int
epoll_wait
(int epfd,
struct epoll_event * events,
int maxevents,
int timeout)
;
引數介紹:
ps:接下來可能說到的有些知識有的同學可能不太懂,不過現在搜尋引擎這麼強大,相信你能找到你不懂知識的答案的。
其實筆者在拿到epoll的這三個函式時是懵的,因為第乙個create函式就讓我產生了極大的困惑,那麼我們就從第乙個函式說起,看看建立這個控制代碼到底幹了什麼。
struct eventpoll
;
其餘的東西不用太關心,但是有倆個東西非常重要。乙個是紅黑樹的頭節點,乙個是就緒檔案描述符鍊錶。這倆個東西就是讓epoll機制效率極大提公升的神器。
我簡單描敘一下這些部分都是用來幹什麼的。
這裡額外需要提到的是,在epoll中每個事件都被乙個epitem結構體描述:
struct epitem
ffd中存放所關心事件的fd和file結構體,其餘的引數都比較好理解。
現在我們來談一談為什麼epoll是高效的,其實通過上面的模型你大體已經可以發現他高效的原因:
這是比較重要的兩條原因,其實epoll已經解決了檔案描述符有上限和介面設計不友好的等等問題。並且使用紅黑樹在進行不重複的插入和進行刪除時都比陣列查詢的on要快的多。
有的同學會說,epoll底層不是使用了記憶體對映麼?這裡為什麼需要進行資料拷貝呢?注意注意注意!筆者之前點開b站有些自稱為epoll深度解析的大佬張口就是記憶體對映,事實上epoll底層並沒有使用對映這種機制,有的人也會質疑我憑什麼你說沒有就沒有。質疑是種好習慣,為了找到事情的真相,下篇部落格不如我們就來**epoll的底層是如何實現的吧。
在說epoll的工作模式之前我們先來舉兩個栗子來幫助我們更簡單的理解epoll的工作模式。
上面倆個栗子其實對應了epoll的兩張工作模式,前者稱為水平觸發level triggered 工作模式,後者稱為邊緣觸發edge triggered工作模式,預設的情況下水平觸發是epoll預設的工作模式,那麼在epoll中怎麼理解呢?
水平觸發
邊緣觸發對比lt和et:其實假如lt模式下每次提示都立刻處理,且每次都將資料讀完避免多次提示那麼效率與et也不會差太多
使用 et 模式的 epoll,需要將檔案描述設定為非阻塞.。這個不是介面上的要求,,而是 「工程實踐」 上的要求。
假設場景,伺服器接受到乙個10k的請求,會向客戶端返回乙個應答資料.。如果客戶端收不到應答,不會傳送第二個10k請求如果服務端寫的**是阻塞式的read,並且一次只 read 1k 資料的話(read不能保證一次就把所有的資料都讀出來,參考 man 手冊的說明,可能被訊號打斷),剩下的9k資料就會待在緩衝區中
所以, 為了解決上述問題(阻塞read不一定能一下把完整的請求讀完), 於是就可以使用非阻塞輪訓的方式來讀緩衝區,保證一定能把完整的請求都讀出來.
而如果是lt沒這個問題. 只要緩衝區中的資料沒讀完, 就能夠讓 epoll_wait 返回檔案描述符讀就緒.
epoll的使用場景一般為:對於多連線, 且多連線中只有一部分連線比較活躍時, 比較適合使用epoll.
產生驚群問題的原因:
如何解決:
本節我們大概的介紹了epoll高效的原因,但是相信很多同學還是處於朦朦朧朧的狀態,那麼我們下節就從epoll的原始碼入手,深度刨析一下epoll的底層到底是怎麼實現的。
Linux I O多路轉接select
系統提供select函式來實現多路復用輸入 輸出模型,那為什麼提供select函式?首先要知道乙個概念,一次i o分兩個部分 等待資料就緒 進行i o 減少等待資料的的比重,增加i o的比重就可以達到高效伺服器的目的。select工作原理就是減少等的比重,同時監控多個檔案描述符 或者說檔案控制代碼 ...
Linux I O多路轉接poll
不同與select使用三個點陣圖來表示三個fdset的方式,poll使用 乙個 pollfd的指標實現。poll函式和select函式的任務相似 等待一組檔案描述符來準備執行i 0。引數 1 第乙個引數 fds struct pollfd 2 第二個引數 nfds nfds用來表示要監視檔案描述符的...
Linux IO多路復用 多路轉接
io多路復用 多路轉接 在沒有io多路復用技術前,程序在同一時間只能監控乙個io狀態 乙個檔案描述符的狀態 例如a和b兩個檔案在操作,定的順序是a前b後,那麼在a阻塞過程中 b在後面也是不能被操作的,這樣會造成資源浪費 響應緩慢。io多路復用 同時監控多個io檔案描述符狀態,如果沒有準備好的描述符 ...