簡明網路I O模型 同步非同步阻塞非阻塞之惑

2022-06-26 09:54:12 字數 3513 閱讀 4340

**:

人多了,就會有問題。web剛出現的時候,光顧的人很少。近年來網路應用規模逐漸擴大,應用的架構也需要隨之改變。c10k的問題,讓工程師們需要思考服務的效能與應用的併發能力。

網路應用需要處理的無非就是兩大類問題,網路i/o資料計算。相對於後者,網路i/o的延遲,給應用帶來的效能瓶頸大於後者。網路i/o的模型大致有如下幾種:

非同步i/o(asynchronous i/o)

網路i/o的本質是socket的讀取,socket在linux系統被抽象為流,i/o可以理解為對流的操作。這個操作又分為兩個階段:

等待流資料準備(wating for the data to be ready)。

從核心向程序複製資料(copying the data from the kernel to the process)。

對於socket流而已,

舉個簡單比喻,來了解這幾種模型。網路io好比釣魚,等待魚上鉤就是網路中等待資料準備好的過程,魚上鉤了,把魚拉上岸就是核心複製資料階段。釣魚的人就是乙個應用程序。

阻塞i/o(bloking i/o)

阻塞i/o是最流行的i/o模型。它符合人們最常見的思考邏輯。阻塞就是程序 "被" 休息, cpu處理其它程序去了。在網路i/o的時候,程序發起recvform系統呼叫,然後程序就被阻塞了,什麼也不幹,直到資料準備好,並且將資料從核心複製到使用者程序,最後程序再處理資料,在等待資料到處理資料的兩個階段,整個程序都被阻塞。不能處理別的網路i/o。大致如下圖:

這就好比我們去釣魚,拋竿之後就一直在岸邊等,直到等待魚上鉤。然後再一次拋竿,等待下一條魚上鉤,等待的時候,什麼事情也不做,大概會胡思亂想吧。

阻塞io的特點就是在io執行的兩個階段都被block了

非阻塞i/o(non-bloking i/o)

在網路i/o時候,非阻塞i/o也會進行recvform系統呼叫,檢查資料是否準備好,與阻塞i/o不一樣,"非阻塞將大的整片時間的阻塞分成n多的小的阻塞, 所以程序不斷地有機會 '被' cpu光顧"。

也就是說非阻塞的recvform系統呼叫呼叫之後,程序並沒有被阻塞,核心馬上返回給程序,如果資料還沒準備好,此時會返回乙個error。程序在返回之後,可以幹點別的事情,然後再發起recvform系統呼叫。重複上面的過程,迴圈往復的進行recvform系統呼叫。這個過程通常被稱之為輪詢。輪詢檢查核心資料,直到資料準備好,再拷貝資料到程序,進行資料處理。需要注意,拷貝資料整個過程,程序仍然是屬於阻塞的狀態。

我們再用釣魚的方式來類別,當我們拋竿入水之後,就看下魚漂是否有動靜,如果沒有魚上鉤,就去幹點別的事情,比如再挖幾條蚯蚓。然後不久又來看看魚漂是否有魚上鉤。這樣往返的檢查又離開,直到魚上鉤,再進行處理。

非阻塞 io的特點是使用者程序需要不斷的主動詢問kernel資料是否準備好。

多路復用i/o(multiplexing i/o)

可以看出,由於非阻塞的呼叫,輪詢佔據了很大一部分過程,輪詢會消耗大量的cpu時間。結合前面兩種模式。如果輪詢不是程序的使用者態,而是有人幫忙就好了。多路復用正好處理這樣的問題。

多路復用有兩個特別的系統呼叫selectpoll。select呼叫是核心級別的,select輪詢相對非阻塞的輪詢的區別在於---前者可以等待多個socket,當其中任何乙個socket的資料準好了,就能返回進行可讀,然後程序再進行recvform系統呼叫,將資料由核心拷貝到使用者程序,當然這個過程是阻塞的。多路復用有兩種阻塞,select或poll呼叫之後,會阻塞程序,與第一種阻塞不同在於,此時的select不是等到socket資料全部到達再處理, 而是有了一部分資料就會呼叫使用者程序來處理。如何知道有一部分資料到達了呢?監視的事情交給了核心,核心負責資料到達的處理。也可以理解為"非阻塞"吧。

對於多路復用,也就是輪詢多個socket。釣魚的時候,我們僱了乙個幫手,他可以同時拋下多個釣魚竿,任何一桿的魚一上鉤,他就會拉桿。他只負責幫我們釣魚,並不會幫我們處理,所以我們還得在一幫等著,等他把收桿。我們再處理魚。多路復用既然可以處理多個i/o,也就帶來了新的問題,多個i/o之間的順序變得不確定了,當然也可以針對不同的編號。

多路復用的特點是通過一種機制乙個程序能同時等待io檔案描述符,核心監視這些檔案描述符(套接字描述符),其中的任意乙個進入讀就緒狀態,select, poll,epoll函式就可以返回。對於監視的方式,又可以分為 select, poll, epoll三種方式。

了解了前面三種模式,在使用者程序進行系統呼叫的時候,他們在等待資料到來的時候,處理的方式不一樣,直接等待,輪詢,select或poll輪詢,第乙個過程有的阻塞,有的不阻塞,有的可以阻塞又可以不阻塞。當時第二個過程都是阻塞的。從整個i/o過程來看,他們都是順序執行的,因此可以歸為同步模型(asynchronous)。都是程序主動向核心檢查。

非同步i/o(asynchronous i/o)

相對於同步i/o,非同步i/o不是順序執行。使用者程序進行aio_read系統呼叫之後,無論核心資料是否準備好,都會直接返回給使用者程序,然後使用者態程序可以去做別的事情。等到socket資料準備好了,核心直接複製資料給程序,然後從核心向程序傳送通知。i/o兩個階段,程序都是非阻塞的。

比之前的釣魚方式不一樣,這一次我們僱了乙個釣魚高手。他不僅會釣魚,還會在魚上鉤之後給我們發簡訊,通知我們魚已經準備好了。我們只要委託他去拋竿,然後就能跑去幹別的事情了,直到他的簡訊。我們再回來處理已經上岸的魚。

通過對上述幾種模型的討論,需要區分阻塞和非阻塞,同步和非同步。他們其實是兩組概念。區別前一組比較容易,後一種往往容易和前面混合。在我看來,所謂同步就是在整個i/o過程。尤其是拷貝資料的過程是阻塞程序的,並且都是應用程序態去檢查核心態。而非同步則是整個過程i/o過程使用者程序都是非阻塞的,並且當拷貝資料的時是由核心傳送通知給使用者程序。

對於同步模型,主要是第一階段處理方法不一樣。而非同步模型,兩個階段都不一樣。這裡我們忽略了訊號驅動模式。這幾個名詞還是容易讓人迷惑,只有同步模型才考慮阻塞和非阻塞,因為非同步肯定是非阻塞,非同步非阻塞的說法感覺畫蛇添足。

本文所討論的io模型來自大名鼎鼎的《unix網路程式設計:卷1套接字聯網api》。單台伺服器中的linux系統。分布式的環境或許會不一樣。個人學習筆記,參考了網路上大多數文章,做了一點小測試。

簡明網路I O模型 同步非同步阻塞非阻塞之惑

人多了,就會有問題。web剛出現的時候,光顧的人很少。近年來網路應用規模逐漸擴大,應用的架構也需要隨之改變。c10k的問題,讓工程師們需要思考服務的效能與應用的併發能力。網路應用需要處理的無非就是兩大類問題,網路i o,資料計算。相對於後者,網路i o的延遲,給應用帶來的效能瓶頸大於後者。網路i o...

網路IO模型(同步非同步,阻塞非阻塞)

摘錄自 網路應用需要處理的無非兩大類問題 網路i o,資料計算 網路io的模型大致有如下幾種 同步模型 阻塞非阻塞 多路復用 訊號驅動式 非同步io 網路io的本質是socket的讀取,socket在linux系統被抽象為流,io可以理解為對流的操作。這個操作分為2個階段 1 等待流資料準備 2 從...

I O模型 阻塞 非阻塞 I O復用 同步 非同步

第一手教育 2016 10 14 11 25 i o模型不論在實際使用還是準備筆試面試中都是重要的內容,參考unix網路程式設計進行總結如下。尤其注意紅色標註處 1.明確i o考察的物件和流程 參考unix網路程式設計,乙個輸入操作通常包括兩個不同的階段 1 等待資料準備好 2 從核心向程序複製資料...