標籤:log 分享 實現 proc ror 執行 png 不同的 緩衝
一、IO模型
1、IO模型分類
1.阻塞IO--------blocking IO
2.非阻塞IO------nonblocking IO
3. 多工IO------- multiplexing
4.訊號驅動IO-------signal driven IO (工作中不會使用到,只是作為瞭解)
5.非同步IO------- asynchronous IO
2、通常情況下IO預設操作分為兩個階段(預設都是阻塞IO)
1.準備等待資料階段,相當於請求作業系統是否有資料發送過來(調用IO操作)。
2.將資料從核心緩衝拷貝到進程緩衝中。
二、不同的IO操作
1、阻塞IO(blocking io)
1.在Linux系統中預設情況下所有的socket都是阻塞IO,
2.阻塞IO工作原理():
當使用者進程調用了recvfrom這個系統調用(相當於使用者進程發送請求像作業系統要資料),kernel就開始了IO的第一個階段:準備 資料。對於network io來說,很多時候資料在一開始還沒有到達,這個時候kernel就要等待足夠的資料到來。而在使用者進程這邊,整個 進程會被阻塞。當kernel一直等到資料準備好了,它就會將資料從kernel中拷貝到使用者記憶體,然後kernel返回結果,使用者進程才解除 block的狀態,重新運行起來。所以,blocking IO的特點就是在IO執行的兩個階段都被block了。
2、非阻塞IO
1.在Linux作業系統可以通過設定socket使其變為non-blocking。當對一個non-blocking socket執行讀操作時,流程是這個樣子
2.非阻塞IO工作原理:
可以看出,當使用者進程發出read操作時,如果kernel中的資料還沒有準備好,那麼它並不會block使用者進程,而是立刻返回一 個error。從使用者進程角度講 ,它發起一個read操作後,並不需要等待,而是馬上就得到了一個結果。使用者進程判斷結果是一個error時,它 就知道資料還沒有準備好,於是它可以再次發送read操作。一旦kernel中的資料準備好了,並且又再次收到了使用者進程的system call,那麼 它馬上就將資料拷貝到了使用者記憶體,然後返回。所以,使用者進程其實是需要不斷的主動詢問kernel資料好了沒有。如果資料還沒準備好,此 時會返回一個error。進程在接收到error後,可以幹點別的事情,然後再發起recvform系統調用。重複上面的過程,迴圈往複的進行recvform 系統調用。這個過程通常被稱之為輪詢。輪詢檢查核心資料,直到資料準備好,再拷貝資料到進程,進行資料處理。需要注意,拷貝資料整 個過程,進程仍然是屬於阻塞的狀態。
3.代碼原理:
3、IO多工
1、以上情況只能應用於一個server處理一個客戶sock,如果想讓一個server處理多個客戶sock那就要用到IO多工
2、多工流程圖:
當使用者進程調用了select,那麼整個進程會被block,而同時,kernel會“監視”所有select負責的socket,當任何一個socket中的 資料準備好了,select就會返回。這個時候使用者進程再調用read操作,將資料從kernel拷貝到使用者進程。這個圖和blocking IO的圖 其實並沒有太大的不同,事實上,還更差一些。因為這裡需要使用兩個system call (select 和 recvfrom),而blocking IO只調用了一 個system call (recvfrom)。但是,用select的優勢在於它可以同時處理多個connection,在IO multiplexing Model中,實際中,對於 每一個socket,一般都設定成為non-blocking,但是,如所示,整個使用者的process其實是一直被block的。只不過process是被 select這個函數block,而不是被socket IO給block。
3.代碼實現原理:
4、利用selectors來實現IO的多工
5、注釋:在windows下只支援python中的select阻塞,而在linux下是三者都支援。我們通過selectors模組python可以自動判斷
使用什麼阻塞方式。
6、各個IO模型比較圖:
走入電腦的第三十九天(python終結篇之IO模型)