io模型 非阻塞模型

2022-08-24 02:24:16 字數 1534 閱讀 8177

linux下,可以通過設定socket使其變為non-blocking。當對乙個non-blocking socket執行讀操作時,流程是這個樣子:

從圖中可以看出,當使用者程序發出read操作時,如果kernel中的資料還沒有準備好,那麼它並不會block使用者程序,而是立刻返回乙個error。從使用者程序角度講 ,它發起乙個read操作後,並不需要等待,而是馬上就得到了乙個結果。使用者程序判斷結果是乙個error時,它就知道資料還沒有準備好,於是使用者就可以在本次到下次再發起read詢問的時間間隔內做其他事情,或者直接再次傳送read操作。一旦kernel中的資料準備好了,並且又再次收到了使用者程序的system call,那麼它馬上就將資料拷貝到了使用者記憶體(這一階段仍然是阻塞的),然後返回。

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

所以,在非阻塞式io中,使用者程序其實是需要不斷的主動詢問kernel資料準備好了沒有。

非阻塞io例項

但是非阻塞io模型絕不被推薦。

我們不能否則其優點:能夠在等待任務完成的時間裡幹其他活了(包括提交其他任務,也就是 「後台」 可以有多個任務在「」同時「」執行)。

但是也難掩其缺點:

#1. 迴圈呼叫recv()將大幅度推高cpu佔用率;這也是我們在**中留一句time.sleep(2)的原因,否則在低配主機下極容易出現卡機情況

#2. 任務完成的響應延遲增大了,因為每過一段時間才去輪詢一次read操作,而任務可能在兩次輪詢之間的任意時間完成。這會導致整體資料吞吐量的降低。

此外,在這個方案中recv()更多的是起到檢測「操作是否完成」的作用,實際作業系統提供了更為高效的檢測「操作是否完成「作用的介面,例如select()多路復用模式,可以一次檢測多個連線是否活躍。for conn in del_l:

conn_l.remove(conn)

conn.close()

del_l=

#客戶端

from socket import *

c=socket(af_inet,sock_stream)

c.connect(('127.0.0.1',8080))

while true:

msg=input('>>: ')

if not msg:continue

c.send(msg.encode('utf-8'))

data=c.recv(1024)

print(data.decode('utf-8'))

非阻塞io例項

非阻塞IO模型

include include include include include include in.h include include include include include using namespace std define maxsize 2048std queue socketqu...

PythonStudy 非阻塞IO模型

服務端 import socket import time import select server socket.socket server.bind 127.0.0.1 1688 server.listen 5 server.setblocking false 預設為阻塞 設定為false 表示...

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

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