1. 程式人生 > >4種常見IO模式詳解

4種常見IO模式詳解

IO模式

本文討論的背景是Linux環境下的網路IO。

對於一次IO訪問,資料會先被拷貝到作業系統核心的緩衝區中,然後從作業系統核心的緩衝區拷貝到應用程式的地址空間。

所以,當發生一個IO操作,它會經歷兩個階段:
1. 等待資料準備
2. 將資料從核心拷貝到程序中

對於兩個階段,linux系統產生了下面五種網路模式的IO儲存方案。

  • 阻塞 I/O(blocking IO)
  • 非阻塞 I/O(nonblocking IO)
  • I/O 多路複用( IO multiplexing)
  • 訊號驅動 I/O( signal driven IO)
  • 非同步 I/O(asynchronous IO)

注:訊號驅動IO在實際中並不常用,所以我們討論剩下的四種IO模式

 

阻塞IO:

在linux中,預設情況下所有的socket都是阻塞io

這個模式的特點在於,當用戶程序呼叫了io操作的時候,作業系統就開始準備資料,作業系統核心一直等到資料準備好了,它就會將資料從作業系統核心中拷貝到使用者記憶體,然後返回結果,使用者程序才解除鎖住的狀態,重新執行起來。整個過程需要等待(不能立刻完成),而使用者程序這邊,就相當於是卡著一直在等他完成返回結果。

所以,阻塞IO的特點就是在IO執行的兩個階段都被鎖住了

 

非阻塞 I/O(nonblocking IO)

linux下,可以通過設定socket使其變為非阻塞IO。

非阻塞IO的特點是,當用戶程序發出IO操作時,在第一個階段如果核心資料還沒準備好,並不會鎖住使用者程序,而是立刻返回一個error。然後使用者程序收到error,就知道沒準備好,就會再去問核心有沒有準備好,直到核心準備好,並且收到了使用者程序的詢問,就會立刻拷貝資料,然後進行第二階段(第二階段依然會卡住,非阻塞IO只是在第一階段非阻塞)

就像打電話一樣,對方佔線,你就一直打,直到對方接通為止,但效率不高。所以,nonblocking IO的特點是使用者程序需要不斷的主動詢問kernel資料好了沒有。

 

I/O 多路複用( IO multiplexing)

IO多路複用就是我們的select,poll,epoll。當用戶程序呼叫了select,那麼整個程序會被block,而同時,kernel會“監視”所有select負責的socket,當任何一個socket中的資料準備好了,select就會返回。這個時候使用者程序再呼叫read操作,將資料從kernel拷貝到使用者程序。簡單的說,就是和阻塞IO處理方式一樣,但不同的是,select可以一下把很多很多檔案描述符都傳過來,然後作業系統核心同時監視他們,只要其中一個就緒,就及時處理那個,而不需要一個個等待處理。

他的效能可能比阻塞IO還要差,但他的優點在於能同時處理多個連線。所以,如果處理的連線數不是很高的話,使用IO多路複用不一定比使用多執行緒+阻塞IO的效能更好,可能延遲還更大。

 

非同步 I/O(asynchronous IO)

Linux下的非同步IO其實用得很少。

非同步io的特點很簡單:當處理一個io操作的時候,使用者程序把資料傳過來,作業系統會立刻返回“收到”,使用者程序就不用管了,可以幹別的事情了。等作業系統核心處理完2個階段,就自動告訴使用者程序我處理完了。

 

總結一下:

阻塞IO:使用者一直等作業系統核心完成2個階段io操作,再繼續

非阻塞IO:第一階段使用者一直問作業系統有沒有準備好,第二階段等作業系統完成。

IO多路複用:使用者程序可以同時發多個網路連線IO,作業系統實施監控,雖然使用者程序2個階段都卡住了,但可以處理多個連線。

非同步IO:使用者程序完全把東西交給作業系統完成,自己不管了。