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í)都會(huì)通知進(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)核會(huì)把這些 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 流,并且會(huì)把就緒的 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í),就會(huì)把就緒的 socket 添加到就緒隊(duì)列中。如 圖3 所示:
當(dāng) socket 從網(wǎng)絡(luò)中獲取到數(shù)據(jù)后,會(huì)發(fā)生通知給 epoll,epoll 會(huì)將當(dāng)前 socket 添加到就緒隊(duì)列中,并且喚醒等待中的進(jìn)程(也就是調(diào)用 epoll_wait 的進(jìn)程)。
當(dāng) socket 狀態(tài)發(fā)生變化時(shí),會(huì)調(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)程被喚醒后,就會(huì)從就緒隊(duì)列中,把就緒的 socket 復(fù)制到用戶提供的數(shù)組中。如 圖4 所示:
如 圖4 所示,在調(diào)用 epoll_wait 時(shí)需要提供一個(gè) events 數(shù)組來存儲(chǔ)就緒的 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文章
7233瀏覽量
90834 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4365瀏覽量
63940 -
epoll
+關(guān)注
關(guān)注
0文章
28瀏覽量
3090
原文標(biāo)題:圖解:epoll怎么實(shí)現(xiàn)的
文章出處:【微信號:LinuxHub,微信公眾號:Linux愛好者】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
兆易創(chuàng)新人形機(jī)器人方案 深度解讀
華為全液冷兆瓦級超充技術(shù)深度解讀

谷歌第七代TPU Ironwood深度解讀:AI推理時(shí)代的硬件革命

英偉達(dá)Cosmos-Reason1 模型深度解讀
飛騰公司榮獲2024年中國產(chǎn)學(xué)研深度融合好案例
PCM1680 does not support a board-to-board interface不支持板對板的是怎么解讀?
解讀MIPI A-PHY與車載Serdes芯片技術(shù)與測試

評論