国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Unix中的IO模型:幫你弄清阻塞VS非阻塞、同步VS異步

2019-11-08 02:41:43
字體:
來源:轉載
供稿:網友

對同步和異步、阻塞和非阻塞這些名詞困惑了很久了,曾經相當然的認為阻塞就是同步、非阻塞就是異步,這也是典型的錯誤,后來從Unix網絡編程卷1上才看到最全面的解析,下面主要的內容來自Unix網絡編程,算是自己的一個學習筆記吧!

由于這本書中面向的是Unix編程,所以在其他的環境中IO模型可能會有稍微的不同,比如java中的IO模型,但是也不會相差很多,畢竟Unix作為眾多技術的鼻祖,很多的思想和實現都來自它。

首先要明白輸入和輸出操作的過程,這個過程包括兩個階段:

等待數據準備好:這里所說的準備好指的是數據已經到硬件設備上了,而不管該數據的來源是什么,可能是通過網線或者無線電傳輸過來的010101,還有可能是本機進程通過系統調用寫到存儲器上的101011,總而言之此時硬件設備上必須要有對應的數據才能算是準備好;將數據從內核中復制到相應的進程中:更明確的說,是通過內核將硬件設備上的數據復制到進程空間中然后進行進一步的操作,這個過程其實是應用進程通過調用內核提供的系統接口完成的。

這個過程如下圖:

這里寫圖片描述

其實在這個過程中內核空間其實是擔當了一個代理人的角色,進程通過調用內核提供的系統接口才能讀取硬件上存儲的數據。所以上面的兩個過程說的更抽象一點:一個是硬件已經存在數據,軟件能夠讀取數據。

由于上圖也涉及到了進程之間的通信,有必要說明一下,進程之間通信不一定要通過操作系統內核,比如共享內存就不會經過內核,但是其他的比如管道等還是會經過內核。

一、阻塞式I/O模型

對于寫過IO程序的人來說,這種模型一定不陌生,不管是使用C還是Java,內部默認的都是這種IO模型,這類所謂的阻塞其實是指應用進程受阻于內核提供的系統調用,該調用直到數據成功返回或者出錯才返回(其他情況下不返回),這時阻塞結束。具體如下圖:

這里寫圖片描述

二、非阻塞式IO模型

所謂非阻塞,是和阻塞式相對應的,不過這種非阻塞也是相對的。與阻塞式中的系統調用返回時機不同,在非阻塞式中當應用進程調用系統接口時,如果數據沒有準備好,則會返回一個標志來標識這種情況,這時系統應用知道數據沒有準備好則不會一直阻塞,而是通過隔一段時間輪詢一次,在兩次輪詢的間隙之間應用進程可以做其他的事情。具體如下圖:

這里寫圖片描述

從上圖可以看出,所謂非阻塞式和阻塞式的區別和聯系在于:

在處理數據的第一階段不同,即確定數據是否準備好; 阻塞式IO模型對這一階段不做任何干涉,如果沒準備好就不返回;非阻塞式IO模型則對內核進行輪詢,如果沒有準備好則返回一個標志,這種方式雖然在一定程度上解放了應用進程,但是卻占用了CPU的大量時間;在處理的數據的第二個階段,兩種模型則是完全相同的;

當然這種模型的實現需要系統內核支持讀取數據時的多狀態標識。

三、IO復用模型

IO復用模型中的“復用”是該模型的核心,究竟復用的是什么?如何進行復用呢?這里還是要聯系上之前的兩個模式,在之前的兩個模式中,應用進程都是直接調用真正的IO系統接口,這個接口是面向應用進行直接讀取硬件上的數據的。但是在IO復用模型中,應用進程直接調用的是一個選擇器select/poll,這個選擇器類似于一個數字電路中的多路開關,如下圖:

這里寫圖片描述

這種模型相當于在應用進程和直接IO系統調用之間添加了一個代理,之前的阻塞和非阻塞模型由于是直接面向IO系統調用的,可以看成為其中有一個隱形的代理,但是只能代理一個IO通道;但是在IO復用模型中,該代理可以代理多個IO通道,所以復用的其實是IO通道 。當有一個IO通道可以進行讀寫時,則select/poll返回告訴應用進程,此時應用進程開始執行對應的讀寫操作,這里需要注意的是select/poll上的通道是需要應用進程自己去注冊的,通道可以是讀操作,也可以是寫操作。具體如下圖:

這里寫圖片描述

從圖中可以看出,IO復用模型與阻塞式和非阻塞式模型的關系如下:

相對于阻塞式模型,從圖中看,其實就是多了上半部分的select選擇器代理,如果當IO通道只有一個的時候,IO復用模型的效率相對于阻塞模型可能會更差一些,因為它經過兩層系統調用,但是當IO通道多的時候,IO復用模型的效率就顯示出來了;相對于非阻塞式模型,相當于將應用進程執行的輪詢操作交給了操作系統內核的select/poll來做,但是非阻塞式模型中輪詢的是一個IO通道的狀態,而IO復用模型中輪詢的是多個IO通道的狀態;IO復用模型是阻塞于select/poll系統調用,而阻塞式模型和非阻塞式模型則是阻塞于直接IO系統調用;

與IO復用模型非常相似的一種模型,是通過多線程結合阻塞式模型,這種阻塞式模型的變體看起來和IO復用模型、非阻塞式模型相同,會讓人誤以為這種模型就是非阻塞式的,IO復用模型和非阻塞時模型的區別上面已經說明,而這種多線程結合阻塞式模型的一個非常大的不同就是它并不需要去輪詢IO通道,而是通過一個線程執行一次系統調用來執行IO系統操作,這樣就不會占用大量CPU的時間,但是維護多線程環境則會占用較多資源,并給編程帶來一些挑戰。

四、信號驅動式IO模型

信號驅動式IO模型與之前的非阻塞時模型和IO復用模型類似,但是對應用進程的通知不是通過輪詢實現的,而是使用信號機制來實現,這就使得在第一階段,等待數據準備的時候,應用進程確確實實的不阻塞,具體如下圖:

這里寫圖片描述

在該圖中可以看出,其實應用進程是調用操作系統內核提供的signal信號處理接口,但是該接口不會造成阻塞而是立即返回。當數據準備好了之后內核則再返回一個信號,告訴應用程序。而之后的過程前面三種模型完全一樣,應用進程仍然會阻塞知道數據復制完畢。從第一個階段的是過程來看,極有可能的一種實現方式就是通過函數回調來完成這種通知

五、異步IO模型

其實在上面的4種模型說明后,異步IO模型就呼之欲出了,在前面4種模型中不管怎么優化,針對的對象都是數據輸入的第一個階段,即等待數據準備好,如果將數據復制過程也考慮進來,那么結果就清晰了,順著信號驅動模IO模型,將信號通知的時機放到數據復制完成之后,就是一步IO模型,這樣從整體上來看,應用進程從來沒有阻塞過,而是一直運行,直到被通知數據已經被復制到自己的空間中了。具體如下:

這里寫圖片描述

六、模型對比

6.1 同步模型之間

上面所說的4種模型:

阻塞式IO模型非阻塞式IO模型IO復用模型信號驅動式IO模型

都是同步模型,它們的主要區別在第一階段,每個模型中應用進程阻塞的實現和方式不同,而在第二個階段則全部相同,都會阻塞于內核復制數據過程。所以不管阻塞和還是不阻塞都是同步模型。它們的區別是在準備數據的過程中,應用進程是不是阻塞。

6.2 同步模型 VS 異步模型

同步模型:導致應用進程阻塞,直到IO操作完成;異步模型:不會造成應用進程阻塞;

上面5種模型的對比如下圖:

這里寫圖片描述

要說明的是,異步和多線程并不是相同的概念,雖然我們在平時經常將兩者混用,其實它們不是一個層次上的概念,異步具體的說是要達到的目的,而多線程只是實現這個目的的一個手段,還有其他的手段,比如多進程,但是由于常用的實現異步的方式就是多線程,所以常常將兩者混淆,因此針對多線程的編程準確的來說應該是并發編程而不是異步編程。所以在上面提到的多線程結合阻塞IO模型,雖然使用了多線程,但是從本質上來說,每個線程對應的仍是阻塞IO模型,所以它也是同步模型,只不過是從主線程來看達到了異步的效果。


相關文章:

關于異步和多線程的關系
上一篇:hdu 2093排序

下一篇:最短路徑問題

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 和顺县| 茌平县| 凤山市| 蒲城县| 大化| 阿克陶县| 道孚县| 涟水县| 长乐市| 天峻县| 会同县| 申扎县| 隆安县| 阳泉市| 霍林郭勒市| 湘阴县| 磐安县| 喀喇沁旗| 翁牛特旗| 大竹县| 新沂市| 武安市| 义马市| 静安区| 英超| 河间市| 安阳县| 剑河县| 新竹县| 晋城| 兴海县| 军事| 太原市| 家居| 临海市| 蓬安县| 宁武县| 开封县| 凯里市| 舟曲县| 鹤峰县|