Linux-I/O模型詳解

I/O介紹

I/O通常有內存IO、網絡I/O、磁盤I/O等,但我們通常說的是網絡I/O以及磁盤I/O。網絡I/O:本質是socket讀取

每次I/O請求,都會有兩個階段組成: 第一步:等待數據,即數據從磁盤到內核內存;將數據從磁盤文件先加載到內核內存空間(緩衝區),等待數據準備完成,時間較長。第二步:複製數據,即數據內核內存到進程內存;將數據從內核緩衝複製到用戶空間的進程內存中,時間較短。

Web請求處理過程

1.客戶端發起情況到服務器網卡2.服務器網卡接受到請求後轉交給內核處理3.內核根據請求對應的套接字,將請求交給工作在用戶空間的Web服務器進程4.Web服務器進程根據用戶請求,向內核進行系統調用,申請獲取相應資源(如:客戶端獲取圖片)5.內核發現Web服務器進程請求的是一個存放在本地硬盤上的資源,因此通過驅動程序連接磁盤6.內核調用磁盤,獲取需要的資源7.內核將資源存放在自己的緩存區中,並通知Web服務器進程8.Web服務器進程通過系統調用取得資源,並將其複製到進程自己的緩衝區中9.Web服務器進程形成響應,通過系統調用再次發給內核以響應請求10.內核將響應發送至網卡11.網卡發送響應給用戶

通過這樣的一個複雜過程,一次請求就完成了

簡單來說就是:

用戶請求——》送達用戶空間——〉系統調用——》內核空間——〉內核到磁盤上讀取圖片資源——》返回到用戶空間——〉響應給用戶

上述簡單的說明了一下,客戶端向Web服務器請求過程,在這個過程中,有兩個I/O過程:一是客戶端請求的網絡I/O,二個是Web服務器請求圖片磁盤I/O。

I/O模型名詞介紹

說到I/O模型,都會牽扯到同步、異步、阻塞、非阻塞這幾個詞,以下講解這幾個詞的概念。

阻塞和非阻塞

阻塞和非阻塞指的是執行一個操作時等操作結束再返回結果,還是馬上返回結果。

阻塞(blocking):指IO操作需要徹底完成後才返回到用戶空間,調用結果返回之前,調用者被掛起(當前線程進入非可執行狀態,在這個狀態,CPU不會分配時間片,線程暫停運行)只有到到結果才進入活動狀態;

阻塞例子:海底撈的服務器爲你點菜,當你點完菜後,服務員把消息傳到後廚,這時你就在餐桌上等待,直到廚師把湯鍋和配菜都準備好以後送到你桌上,你才能開喫。在上菜的過程中你還不能離開,因爲你離開了之後服務員上菜了卻找不到你人,所以你就是能等待,這個時候你處於阻塞等待狀態,就是前面說的,你是調用者,你被掛起了,進入了非可執行狀態。

非阻塞(nonblocking):指I/O操作被調用後立即返回給用戶一個狀態值,無需等到I/O操作徹底完成,最終的調用結果返回之前,調用者不會被掛起;

非阻塞例子:海底撈的服務器爲你點菜,當你點完菜後,服務員把消息傳到後廚,過了三分鐘,你跑到後廚問,我的鍋底或者肥牛卷好了沒有?後廚說沒好,然後你去處理其它事情,然後又過了五分鐘,你又跑到後廚問,我的某個菜好了沒有,如果沒有,你還是繼續做其他事情,然後等會再問一次,這個時候就是在I/O操作的同時,你沒有被掛起,可以操作其他事情,但是如果I/O操作完成,你需要立馬接受。

同步和異步

同步/異步關注的是消息通信機制

同步(synchronous):調用者等待被調用者返回消息,才能繼續執行。同步阻塞例子:去餐館喫飯,點了一個蓋澆飯,然後在餐桌上一直等到蓋澆飯做好,自己端到餐桌就餐。這就是典型的同步阻塞。當廚師給你做飯的時候,你需要一直在那裏等着。

同步非阻塞例子:去餐館喫飯,點了一個蓋澆飯,你點完飯之後,過了幾分鐘感覺時間差不多了,就去問老闆飯做好了沒有,如果好了就去端,如果沒好等一會再去問,實時同步做飯進度,依次循環去問直到飯做好,這就是同步非阻塞。 異步(asynchronous):被調用者通過狀態、通知或回調機制主動通知調用者被調用者的運行狀態。

I/O模型類型

IO模型分爲以下五類

1.阻塞型:所有過程全阻塞2.非阻塞型:如果沒有數據buffer,則立即返回EWOULDBLOCK3.I/O複用型(select和poll):在wait和copy階段分別阻塞4.信號驅動型I/O(SIGIO):在wait階段不阻塞,但copy階段阻塞(信號驅動I/O),即通知5.異步I/O(AIO):完全無阻塞方式,當I/O完成時提供信號

阻塞I/O

說明:應用程序調用一個IO的recvfrom函數,會導致應用程序阻塞,進入阻塞狀態後直到I/O操作結束纔會返回;如果系統內核數據沒有準備好,那就一直等待數據準備,因爲是調用了recvfrom函數導致了應用程序阻塞,所以一直在等,做不了任何事情,內核數據準備好之後把數據從內核拷貝到用戶空間,拷貝結束後,I/O函數返回成功指示。注:其阻塞時在I/O操作階段

非阻塞I/O

說明:用戶線程發起IO請求時立即返回。但並未讀取到任何數據,則返回字段爲“EWOULDBLOCK”,用戶線程需要不斷地發起IO請求,直到數據到達後,才真正讀取到數據,繼續執行。即“輪詢”機制。整個IO請求過程中,雖然用戶線程每次發起IO請求後可以立即返回,但是爲了等到數據。仍需要不斷地輪詢、重複請求、消耗了大量的CPU資源;是比較浪費CPU的方式,一般很少用這種模型,而是在其他模型中使用非阻塞IO這一特性。

I/O複用(select和poll)

說明:I/O複用模型會用到select或poll函數,在I/O複用模型中,並不是阻塞到I/O操作過程中,而是阻塞到select或者poll函數中;以select爲例:進程在select處阻塞,等待幾個描述符中的一個變爲可操作,如果沒等待到就繼續阻塞在第一階段,如果等到了一個描述符變爲了可操作,則調用recvfrom函數將數據拷貝到應用緩衝區。

信號驅動I/O(SIGIO)

說明:首先,我們允許套接口進行信號驅動I/O,並安裝一個信號處理函數SIGIO,如果數據沒有準備好,則立即返回結果,進程繼續工作並不阻塞。當數據準備好時,系統內核會主動發送一個SIGIO信號給應用程序,應用程序收到信號後,可以在信號處理函數中調用I/O操作函數recvfrom進行數據處理。信號驅動I/O模型的優點是當數據報到達時,可以不阻塞,主循環可以繼續執行,只是等待處理程序的通知,或者數據已經準備好被處理,或者數據報已經準備好被讀了。

異步I/O(AIO)

說明:當一個異步過程調用發出後,調用者不能立刻得到結果。實際處理這個調用的部件在完成後,通過狀態通知和回調通知來告訴調用者的輸入輸出操作。用戶可以直接對I/O執行讀寫操作,這些操作告訴內核用戶讀寫緩衝區的位置,以及I/O操作完成之後內核通知應用程序的方式,就是上面講的通過狀態通知或者回調通知來告訴調用者。異步I/O的讀寫操作總是立即返回,但沒有返回結果說是否阻塞,因爲異步I/O操作真正的讀寫操作已由內核接管,內核自己對數據處理完成後生成一個信號,然後通知用戶剛纔交給自己的事件已經處理完成。

五種I/O模型的總結及比較

中文圖示如下:

英文圖示如下:

從兩張圖中我們可以看到,越往後,阻塞越少,理論上效率也是最優。其中五種I/O模型中,前三種屬於同步I/O,後兩者屬於異步I/O。

同步I/O

阻塞I/O 非阻塞I/O I/O複用(select和poll)

異步I/O

信號驅動I/O(SIGIO) 半異步 異步I/O(AIO) 全異步

異步I/O和信號驅動I/O的區別

信號驅動I/O模式下,內核可以複製的時候通知給我們應用程序發送SIGIO信號。異步I/O模式下,內核在所有的操作由內核操作完成後纔會通知我們的應用程序。

參考來源:

https://blog.csdn.net/wscdylzjy/article/details/45748153

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章