自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

圖解 | Epoll怎么實(shí)現(xiàn)的

系統(tǒng)
epoll 可以說是編寫高性能服務(wù)端程序必不可少的技術(shù),在介紹 epoll 之前,我們先來了解一下 多路復(fù)用I/O 吧。

 [[394368]]

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 句柄快速找到對(duì)應(yīng)的 socket 對(duì)象。

就緒隊(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ù)的處理過程:

  1. static int ep_poll_callback(wait_queue_t *wait, unsigned mode,  
  2.                             int sync, void *key
  3.     ... 
  4.     struct epitem *epi = ep_item_from_wait(wait); 
  5.     struct eventpoll *ep = epi->ep; 
  6.     ... 
  7.     // 1) 把 socket 添加到就緒隊(duì)列中 
  8.     list_add_tail(&epi->rdllink, &ep->rdllist); 
  9.  
  10. is_linked: 
  11.     // 2) 喚醒調(diào)用 epoll_wait() 而被阻塞的進(jìn)程 
  12.     if (waitqueue_active(&ep->wq)) 
  13.         wake_up_locked(&ep->wq); 
  14.     ... 
  15.     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,并可對(duì)其進(jìn)行讀寫操作。

總結(jié)

本文主要通過圖解的方式大概介紹了 epoll 的原理,但很多實(shí)現(xiàn)的細(xì)節(jié)只能通過閱讀源碼來了解。如果對(duì) epoll 的實(shí)現(xiàn)有興趣,可以參考《epoll 如何工作的》這篇文章。

 

責(zé)任編輯:武曉燕 來源: Linux內(nèi)核那些事
相關(guān)推薦

2021-06-26 07:04:24

Epoll服務(wù)器機(jī)制

2023-01-04 13:43:24

讀寫鎖AQS共享模式

2022-06-07 10:40:56

流程數(shù)據(jù)庫MySQL

2021-07-07 10:05:38

進(jìn)程CPULinux

2021-03-30 09:45:11

悲觀鎖樂觀鎖Optimistic

2022-06-20 08:03:17

KafkaJava NIO

2020-12-09 10:29:53

SSH加密數(shù)據(jù)安全

2021-09-30 10:45:33

Linux進(jìn)程通信

2015-10-21 10:24:05

TCPIP網(wǎng)絡(luò)協(xié)議

2021-07-14 09:48:15

Linux源碼Epoll

2023-01-27 18:08:35

eBPF云原生

2023-03-11 11:19:07

loopbackSocket

2011-04-01 13:55:58

路由路由器路由表

2009-12-31 09:12:30

華為ADSL設(shè)置

2011-04-01 13:32:27

路由路由器

2021-05-11 08:22:32

Epoll 監(jiān)聽I

2011-04-01 14:15:37

路由篩選器

2023-05-29 08:31:48

Redis散列表

2022-03-07 09:42:21

Go快速排序

2020-04-02 09:58:26

Kubernetes容器開發(fā)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)