epoll 可以說是編寫高性能服務(wù)端程序必不可少的技術(shù),在介紹 epoll 之前,我們先來了解一下 多路復(fù)用I/O 吧。
多路復(fù)用I/O多路復(fù)用I/O:是指內(nèi)核負(fù)責(zé)監(jiān)聽多個(gè) I/O 流,當(dāng)任何一個(gè) I/O 流處于就緒狀態(tài)(可讀或可寫)時(shí)都會通知進(jìn)程,以便可以處理該 I/O 流上的數(shù)據(jù)。如 圖1 所示:
如 圖1 所示,內(nèi)核負(fù)責(zé)監(jiān)聽多個(gè) I/O 流,當(dāng)某些 I/O 流變?yōu)榫途w狀態(tài),內(nèi)核會把這些 I/O 流添加到就緒隊(duì)列中,然后通知進(jìn)程處理就緒隊(duì)列中的 I/O 流。
與傳統(tǒng)的阻塞型 I/O 相比,多路復(fù)用 I/O 的優(yōu)點(diǎn)是可以同時(shí)監(jiān)聽多個(gè) I/O 流,并且會把就緒的 I/O 流告知進(jìn)程。
epoll原理介紹完多路復(fù)用 I/O,接下來開始介紹我們的主角:epoll。
在 Linux 系統(tǒng)中,有多種多路復(fù)用 I/O 的實(shí)現(xiàn),比如 select 和 poll 等。而 epoll 也是多路復(fù)用 I/O 一種實(shí)現(xiàn),與 select 和 poll 相比,epoll 在性能上有較大的提升。
紅黑樹
epoll 內(nèi)部使用紅黑樹來保存所有監(jiān)聽的 socket,紅黑樹是一種平衡二叉樹,添加和查找元素的時(shí)間復(fù)雜度為 O(log n),其結(jié)構(gòu)如 圖2 所示:
epoll 通過 socket 句柄來作為 key,把 socket 保存在紅黑樹中。如 圖2 所示,每個(gè)節(jié)點(diǎn)中的數(shù)字代表著 socket 句柄。
把監(jiān)聽的 socket 保存在紅黑樹中的目的是,為了在修改監(jiān)聽 socket 的讀寫事件時(shí),能夠通過 socket 句柄快速找到對應(yīng)的 socket 對象。
就緒隊(duì)列
另外,epoll 還維護(hù)著一個(gè)就緒隊(duì)列,當(dāng) epoll 監(jiān)聽的 socket 狀態(tài)發(fā)生改變(變?yōu)榭勺x或可寫)時(shí),就會把就緒的 socket 添加到就緒隊(duì)列中。如 圖3 所示:
當(dāng) socket 從網(wǎng)絡(luò)中獲取到數(shù)據(jù)后,會發(fā)生通知給 epoll,epoll 會將當(dāng)前 socket 添加到就緒隊(duì)列中,并且喚醒等待中的進(jìn)程(也就是調(diào)用 epoll_wait 的進(jìn)程)。
當(dāng) socket 狀態(tài)發(fā)生變化時(shí),會調(diào)用 ep_poll_callback 函數(shù)來通知 epoll,我們來看看這個(gè)函數(shù)的處理過程:
static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *key){ 。。. struct epitem *epi = ep_item_from_wait(wait); struct eventpoll *ep = epi-》ep; 。。. // 1) 把 socket 添加到就緒隊(duì)列中 list_add_tail(&epi-》rdllink, &ep-》rdllist);
is_linked: // 2) 喚醒調(diào)用 epoll_wait() 而被阻塞的進(jìn)程 if (waitqueue_active(&ep-》wq)) wake_up_locked(&ep-》wq); 。。. return 1;}
ep_poll_callback 函數(shù)的意圖很清晰,主要完成兩個(gè)工作:
把就緒的 socket 添加到就緒隊(duì)列中。
喚醒調(diào)用 epoll_wait 函數(shù)而被阻塞的進(jìn)程。
當(dāng)進(jìn)程被喚醒后,就會從就緒隊(duì)列中,把就緒的 socket 復(fù)制到用戶提供的數(shù)組中。如 圖4 所示:
如 圖4 所示,在調(diào)用 epoll_wait 時(shí)需要提供一個(gè) events 數(shù)組來存儲就緒的 socket。當(dāng) epoll_wait 返回后,用戶就可以從events 數(shù)組中獲取到就緒的 socket,并可對其進(jìn)行讀寫操作。
總結(jié)本文主要通過圖解的方式大概介紹了 epoll 的原理,但很多實(shí)現(xiàn)的細(xì)節(jié)只能通過閱讀源碼來了解。
編輯:jq
-
數(shù)據(jù)
+關(guān)注
關(guān)注
8文章
7145瀏覽量
89592 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4346瀏覽量
62979 -
epoll
+關(guān)注
關(guān)注
0文章
28瀏覽量
2985
原文標(biāo)題:圖解:epoll怎么實(shí)現(xiàn)的
文章出處:【微信號:LinuxHub,微信公眾號:Linux愛好者】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
3D深度感測的原理和使用二極管激光來實(shí)現(xiàn)深度感測的優(yōu)勢
![3D<b class='flag-5'>深度</b>感測的原理和使用二極管激光來實(shí)現(xiàn)<b class='flag-5'>深度</b>感測的優(yōu)勢](https://file1.elecfans.com/web3/M00/05/0B/wKgZPGd8ic-AckhBAAAQe8tjUNc907.jpg)
PCM1680 does not support a board-to-board interface不支持板對板的是怎么解讀?
FPGA做深度學(xué)習(xí)能走多遠(yuǎn)?
解讀MIPI A-PHY與車載Serdes芯片技術(shù)與測試
![<b class='flag-5'>解讀</b>MIPI A-PHY與車載Serdes芯片技術(shù)與測試](https://file1.elecfans.com/web2/M00/FE/12/wKgZomagZB6AC_wWAAAmrT3twR4378.png)
ESP32 深度睡眠
為什么深度睡眠期間RTC定時(shí)器會丟失呢?
解讀PyTorch模型訓(xùn)練過程
深度學(xué)習(xí)的典型模型和訓(xùn)練過程
深度解析深度學(xué)習(xí)下的語義SLAM
![<b class='flag-5'>深度</b>解析<b class='flag-5'>深度</b>學(xué)習(xí)下的語義SLAM](https://file1.elecfans.com/web2/M00/D6/82/wKgZomYnfe-ARm_pAAAcYiwkMFk951.png)
深度解讀廣汽全固態(tài)電池技術(shù)
![<b class='flag-5'>深度</b><b class='flag-5'>解讀</b>廣汽全固態(tài)電池技術(shù)](https://file1.elecfans.com/web2/M00/C9/5D/wKgaomYcf_-AK_K_AAAKxLiV-Jw221.jpg)
評論