1. 程式人生 > >IO:阻塞、非阻塞、同步、非同步

IO:阻塞、非阻塞、同步、非同步

Network I/O:阻塞(blocking)、非阻塞(nonblocking)、同步(synchronous)、非同步(asynchronous)I/O涉及到兩個系統物件:(1)呼叫I/O的process(thread),(2)系統核心(kernel)。I/O操作發生時經歷兩個階段:(1)等待資料ready,(2)將資料從核心拷貝到程序中。# 阻塞IO當用戶程序呼叫了recvfrom這個系統呼叫,kernel就開始了IO的第一個階段:(1)準備資料。很多時候資料在一開始還沒有到達(比如,還沒有收到一個完整的UDP包),這時kernel就要等待足夠的資料到來。在使用者程序這邊,整個程序會被阻塞。(2)當kernel一直等到資料準備好了,它就會將資料從kernel中拷貝到使用者記憶體,然後kernel返回結果,
使用者程序才解除阻塞狀態,重新執行起來。阻塞IO的特點是在IO執行的兩個階段都被block了。
# 非阻塞IO當用戶程序呼叫了recvfrom這個系統呼叫,如果kernel中的資料還沒有準備好,它並不會block使用者程序,而是立刻返回error(EWOULDBLOCK)。使用者程序判斷結果是一個error時,它就知道資料還沒有準備好,於是它可以再次發生recvfrom操作。一旦kernel中的資料準備好了,並且又再次收到了使用者程序的system call,那麼它馬上將資料拷貝到了使用者記憶體,然後返回。使用者程序其實是在不斷的主動詢問kernel資料好了沒有
# IO複用(I/O Multiplexing):select, poll
select/poll的好處在於單個使用者process可以處理多個網路連線的IO。它的基本原理是:select/poll函式會不斷的輪詢所負責的所有socket,當某個socket有資料到達了,就通知使用者程序。當用戶程序呼叫了select,整個程序就會被block。同時kernel會監視所有select負責的socket,當任何一個socket中的資料準備好了,select就會返回。這時使用者程序再呼叫read操作,將資料從kernel拷貝到使用者程序。實際中,在IO Multiplexing模型中,對於每一個socket,一般都設定為non-blocking。但是整個使用者程序其實一直是被block的
,只不過是被select函式block,而不是被socket IO給block。

# 非同步IO當用戶程序呼叫read操作後,就立刻開始去做其他事情。從kernel的角度看,當它收到一個非同步read之後,首先會立刻返回,所以不會對使用者程序產生任何block。然後kernel會等待資料準備完成,然後將資料拷貝到使用者記憶體。當這一切都完成之後,kernel會給使用者程序傳送一個signal,告訴它read操作完成了。
# 同步IO和非同步IOA synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes.An asynchronous I/O operation does not cause the requesting process to be blocked.兩者的區別是synchronous I/O在做"I/O operation"的時候會將process阻塞。阻塞IO、非阻塞IO、IO複用都屬於同步IO。定義中的"I/O operation"是指真實的IO操作,也就是例子中的recvfrom這個system call。非阻塞IO在執行recvfrom這個system call時,如果kernel的資料沒有準備好,這個時候不會block程序。當kernel中資料準備好的時候,recvfrom會將資料從kernel拷貝到使用者記憶體中,這個時候程序是被block的。非同步IO則不一樣,當程序發起IO操作之後,就直接返回再也不理睬了,直到kernel發生一個訊號,告訴程序IO完成。在整個過程中,程序完全沒有被block。



參考: