您好,登錄后才能下訂單哦!
本篇內容主要講解“如何理解常見的IO模型:阻塞、非阻塞、多路復用、異步”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“如何理解常見的IO模型:阻塞、非阻塞、多路復用、異步”吧!
在Unix網絡編程中,史蒂文斯給出了5種IO編程模型,其中最重點、也最常用的是多路復用模型(Multiplexing)。 這5種模型分別為:
阻塞式IO
非阻塞式IO
IO多路復用(multiplexing io),基于select/poll/epoll
信號驅動式IO SIGIO
異步IO(posix aio_abi和libaio)
想要說明清楚這幾個模型,一個很好的方式是把網絡IO分為兩個階段來理解。第一階段,從客戶端向服務端發送請求開始,到數據從網絡傳輸到達,完全準備好為止。第二階段,數據從內核空間復制到程序緩存(即用戶空間),這個階段才是應用真正執行recvfrom
系統調用的階段。在第一階段,程序要么阻塞在recvfrom
調用上,要么阻塞在select
之類的方法上,或者干其他的事情去了(輪詢、異步等)。
有了這個基本認知,我們再來逐個審視這幾種模型。
阻塞式IO(blocking I/O)是最基本的IO模型,也是日常使用中默認的模式。
如上圖,應用發出請求,試圖執行recvfrom
系統調用,以獲取數據,由于數據還沒準備好(也許服務端才開始處理請求),當前請求線程被阻塞,只能傻傻的等待,直到數據可讀或者拋出異常。如果是單線程應用,主線程掛起,CPU空置。如果是多線程,當前線程掛起,CPU切換時間片去執行其他線程。
一般的Socket
對象都會有一個setblocking(False)
或者ConfigureBlocing(false)
之類的方法,將當前IO線程設置成非阻塞模式。
如圖,當socket設置為nonblocking時,在一階段(數據準備階段,還記得前面說的二階段IO么,這里派上了用場)線程會不斷的發起recvfrom
輪詢,如果還沒有準備好數據,會得到一個EWouldBLOCK
錯誤信號,直到數據準備好之后,開始真正執行recvfrom
拉取數據。輪詢會極大的消耗CPU時間,所以這種模型極少用到。
I/O復用,即I/O multiplexing,這是一種基于select
函數的編程模型,也是最常用的一種。有些人喜歡把它稱作異步阻塞模型,我覺得這種叫法很容易讓人產生誤解,實際上這個模型和所謂的異步I/O沒有半毛錢關系。
如上圖,在第一階段,我們可以通過select函數注冊多路IO對象。每一個注冊的IO對象都會阻塞在select
函數上,直到IO對象的狀態發生改變。此時數據已經準備好讀/寫。調度器遍歷這些IO對象,返回準備好讀/寫的IO對象。緊接著進入第二階段,開始對準備好的IO對象調用recvfrom
函數。
對于多路復用模型,Java NIO基于select
庫實現了調度器Selector
,python的selectors
模塊分別提供了基于select
、poll
以及epoll
庫的封裝對象。
通過以上過程,我們還可以看到,其實IO多路復用跟阻塞IO很相似,基本兩個階段都在阻塞狀態。只不過前者第一階段阻塞在select
函數上,第二階段阻塞在recvfrom
調用上;而后者全程阻塞在recvfrom
上。而且IO多路復用由于需要注冊、遍歷IO對象,其實涉及到更多的步驟開銷。但是多路復用的優勢正在于可以同時對接多個IO對象,結合多線程技術,可以帶來很大的靈活性。
前面提到的三種模型,本質上在真正的IO階段(第二階段),都會阻塞。而在異步IO模型中,應用發出數據請求后,不再等待,直接返回。期間線程也不會阻塞。之后由內核處理兩個階段IO,然后給應用發送信號,程序直接獲取數據。
基于Unix系統有一個POSIX異步IO庫——aio_abi
,以及一個第三方庫aiolib
,后者可能更加知名。異步IO模型非常復雜,一般很少見到。另外我也有一些疑惑,python中的asyncio
包提出的協程概念,和這里的異步IO是否為同一件事物。史蒂文斯在這里描述的異步明顯需要基于系統內核的相關實現,和asyncio這種單純的編程概念,大概說的不是一個層級的東西吧。
最后還是說一個比喻吧。如果把IO模型比作網購,在你提交訂單的一刻到快遞員將貨物帶到你家小區門口期間,可看作一階段IO。之后小哥給你打電話:“你的快遞,快開門”,這相當于數據準備好了,并發送了通知。之后,你跑到門口將快遞一件一件搬到家里,這是第二階段。
阻塞模型相當于你提了訂單,就不吃不喝,只等著快遞,直到小哥給你打電話,然后吭哧吭哧把快遞搬到家,你才開始吃喝、睡覺等。非阻塞模型下,你提交訂單后就開始自由行動了。但是仍然會每隔幾分鐘跑到小區門口看看快遞到了沒(輪詢),一直把自己搞得精疲力盡。直到小哥給你打電話,你把快遞搬回家才算消停。多路復用模型下,你同時提交了多個訂單,但不再傻傻的朝門口來回跑了,而是緊緊盯著菜鳥裹裹信息(阻塞在select),直到其上顯示至少有一個快遞到了,你會嗖的跑過去,當然,快遞仍然自己搬(recvfrom阻塞)。異步模型下,你雇了一個萬能管家吉福斯,你只要下完訂單,就不用操心了,他會打點好一切,最后他會把快遞按照你們約定的地點、方式,直接送到你的手上。
到此,相信大家對“如何理解常見的IO模型:阻塞、非阻塞、多路復用、異步”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。