Linux I O多路轉接epoll技術

2021-09-26 01:29:19 字數 2980 閱讀 3739

前面的兩篇部落格我們已經為大家介紹了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檔案描述符狀態,如果沒有準備好的描述符 ...