IO模型(epoll) 詳解 01

2022-07-20 16:36:13 字數 2765 閱讀 4402

從事服務端開發,少不了要接觸網路程式設計。epoll作為linux下高效能網路伺服器的必備技術至關重要,nginx、redis、skynet和大部分遊戲伺服器都使用到這一多路復用技術。

一、從網絡卡接收資料說起

二、如何知道接收了資料?

三、程序阻塞為什麼不占用cpu資源?

四、核心接收網路資料全過程

五、同時監視多個socket的簡單方法

六、epoll的設計思路

七、epoll的原理和流程

八、epoll的實現細節

九、結論

下圖是乙個典型的計算機結構圖,計算機由cpu、儲存器(記憶體)、網路介面等部件組成。了解epoll本質的第一步,要從硬體的角度看計算機怎樣接收網路資料。

下圖展示了網絡卡接收資料的過程。在①階段,網絡卡收到網線傳來的資料;經過②階段的硬體電路的傳輸;最終將資料寫入到記憶體中的某個位址上(③階段)。這個過程涉及到dma傳輸、io通路選擇等硬體有關的知識,但我們只需知道:網絡卡會把接收到的資料寫入記憶體。

了解epoll本質的第二步,要從cpu的角度來看資料接收。要理解這個問題,要先了解乙個概念——中斷。

計算機執行程式時,會有優先順序的需求。比如,當計算機收到斷電訊號時(電容可以儲存少許電量,供cpu執行很短的一小段時間),它應立即去儲存資料,儲存資料的程式具有較高的優先順序。

一般而言,由硬體產生的訊號需要cpu立馬做出回應(不然資料可能就丟失),所以它的優先順序很高。cpu理應中斷掉正在執行的程式,去做出響應;當cpu完成對硬體的響應後,再重新執行使用者程式。中斷的過程如下圖,和函式呼叫差不多。只不過函式呼叫是事先定好位置,而中斷的位置由「訊號」決定。

以鍵盤為例,當使用者按下鍵盤某個按鍵時,鍵盤會給cpu的中斷引腳發出乙個高電平。cpu能夠捕獲這個訊號,然後執行鍵盤中斷程式。下圖展示了各種硬體通過中斷與cpu互動。

現在可以回答本節提出的問題了:當網絡卡把資料寫入到記憶體後,網絡卡向cpu發出乙個中斷訊號,作業系統便能得知有新資料到來,再通過網絡卡中斷程式去處理資料。

了解epoll本質的第三步,要從作業系統程序排程的角度來看資料接收。阻塞是程序排程的關鍵一環,指的是程序在等待某事件(如接收到網路資料)發生之前的等待狀態,recv、select和epoll都是阻塞方法。了解「程序阻塞為什麼不占用cpu資源?」,也就能夠了解這一步。

為簡單起見,我們從普通的recv接收開始分析,先看看下面**:

//建立socket

int s = socket(af_inet, sock_stream, 0

);

//繫結

bind(s, ...)

//監聽

listen(s, ...)

//接受客戶端連線

int c =accept(s, ...)

//接收客戶端資料

recv(c, ...);

//將資料列印出來

printf(...)

這是一段最基礎的網路程式設計**,先新建socket物件,依次呼叫bind、listen、accept,最後呼叫recv接收資料。recv是個阻塞方法,當程式執行到recv時,它會一直等待,直到接收到資料才往下執行。

工作佇列

作業系統為了支援多工,實現了程序排程的功能,會把程序分為「執行」和「等待」等幾種狀態。執行狀態是程序獲得cpu使用權,正在執行**的狀態;等待狀態是阻塞狀態,比如上述程式執行到recv時,程式會從執行狀態變為等待狀態,接收到資料後又變回執行狀態。作業系統會分時執行各個執行狀態的程序,由於速度很快,看上去就像是同時執行多個任務。

下圖中的計算機中執行著a、b、c三個程序,其中程序a執行著上述基礎網路程式,一開始,這3個程序都被作業系統的工作佇列所引用,處於執行狀態,會分時執行。

工作佇列中有a、b和c三個程序

等待佇列

當程序a執行到建立socket的語句時,作業系統會建立乙個由檔案系統管理的socket物件(如下圖)。這個socket物件包含了傳送緩衝區、接收緩衝區、等待佇列等成員。等待佇列是個非常重要的結構,它指向所有需要等待該socket事件的程序。

當程式執行到recv時,作業系統會將程序a從工作佇列移動到該socket的等待佇列中(如下圖)。由於工作佇列只剩下了程序b和c,依據程序排程,cpu會輪流執行這兩個程序的程式,不會執行程序a的程式。所以程序a被阻塞,不會往下執行**,也不會占用cpu資源。

ps:作業系統新增等待佇列只是新增了對這個「等待中」程序的引用,以便在接收到資料時獲取程序物件、將其喚醒,而非直接將程序管理納入自己之下。上圖為了方便說明,直接將程序掛到等待佇列之下。

喚醒程序

當socket接收到資料後,作業系統將該socket等待佇列上的程序重新放回到工作佇列,該程序變成執行狀態,繼續執行**。也由於socket的接收緩衝區已經有了資料,recv可以返回接收到的資料。

IO復用模型 epoll

參見 1.epoll模型簡介 epoll是linux多路服用io介面select poll的加強版,e對應的英文單詞就是enhancement,中文翻譯為增強,加強,提高,充實的意思。所以epoll模型會顯著提高程式在大量併發連線中只有少量活躍的情況下的系統cpu利用率。epoll把使用者關心的檔案...

多路I O轉接之epoll模型

epoll是linux下多路復用io介面select poll的增強版本,它能顯著提高程式在大量併發連線中只有少量活躍的情況下的系統cpu利用率,因為它會復用檔案描述符集合來傳遞結 果而不用迫使開發者每次等待事件之前都必須重新準備要被偵聽的檔案描述符集合,另一點原因就是獲取事件的時候,它無須遍歷整個...

linux的epoll模型詳解

1.epoll是何方神聖?epoll可是當前在linux下開發大規模併發網路程式的熱門人選,epoll 在linux2.6核心中正式引入,和select相似,其實都i o多路復用技術而已,並沒有什麼神秘的。其實在linux下設計併發網路程式,向來不缺少方法,比如典型的apache模型 process...