Linux_I/O模型

I/O模型(I/O Models)


  • 阻塞式I/O(blocking I/O)
  • 非阻塞式I/O(nonblocking I/O)
  • I/O多路複用(I/O multiplexing)
  • 信號驅動I/O(signal driven I/O)
  • 異步I/O(asynchronous I/O)

對於一個network I/O涉及兩個系統對象,一個是調用I/O的進程(process),另一個是系統內核(kernel)。

下面用read操作來當做例子,當一個read操作發生時涉及的兩個步驟:

  • 等待內核將數據準備好
  • 內核將準備好的數據拷貝到進程,也就是從kernel space拷貝到user space

對於一個socket的read操作,第一步通常是等待網絡數據。當包到達時,會先拷貝到內核的內存中。然後第二步,把數據從內核的緩衝區拷貝到應用程序的緩衝區。


阻塞式I/O(blocking I/O)

在這裏插入圖片描述

姜太公釣魚,願者上鉤。魚竿丟下去,就等到魚上來,啥事不幹,啥事也幹不了。

當應用程序調用recvfrom這個system call,kernel只有等到準備好數據,把數據拷貝到應用程序的緩衝區,纔會返回。應用程序在調用recvfrom後,如果kernel沒有準備好數據,會被“睡覺”。進程一直阻塞着,在呼叫recvfrom這個system call之後,直到kernel返回數據,或者錯誤。

blocking IO的特點就是在IO執行的兩個階段都被block了。


非阻塞式I/O(nonblocking I/O)

在這裏插入圖片描述

魚竿下去,想看B站,看一會B站,看一下魚釣到沒。

非阻塞式I/O和阻塞式I/O很大的區別就在於,應用程序調用recvfrom,馬上會有返回,如果kernel還沒準備好數據,會返回錯誤EWOULDBLOCK。從用戶進程角度講 ,它發起一個read操作後,並不需要等待,而是馬上就得到了一個結果。應用程序收到error的返回,會再呼叫recvfrom。如果kernel準備好數據,就會把數據拷貝到應用程序的緩存區,返回。

如果一個應用程序處於類似循環呼叫recvfrom這個操作,這個稱爲polling,輪詢

這個模型比較浪費CPU時間。

注意,非阻塞式I/O算是同步I/O,雖然在呼叫recvfrom會立刻收到返回,但是在copy datagram那裏是阻塞的,所以算是同步I/O


I/O複用(I/O Multiplexing Model)

在這裏插入圖片描述

一個魚竿太少了,就買20根魚竿,不斷看哪根魚竿釣到魚了。

I/O複用,相比阻塞式I/O和非阻塞式I/O,會呼叫兩個system call,一般由select,poll,epoll實現。這裏用select先 當例子。

應用程序在呼叫select之後被阻塞,直到返回有data可以讀。當select返回有data可以讀,應用程序就呼叫recvfrom把data copy到應用程序的緩衝區。

相比較阻塞式I/O和非阻塞式I/O,這個模式沒有優化什麼,但是最大的優點是可以處理多條連接

在IO multiplexing Model中,實際中,對於每一個socket,一般都設置成爲non-blocking,但是,如上圖所示,整個用戶的process其實是一直被block的。只不過process是被select這個函數block,而不是被socket IO給block。

如果處理的連接數不是很高的話,使用select/epoll的web server不一定比使用multi-threading + blocking IO的web server性能更好,可能延遲還更大。select/epoll的優勢並不是對於單個連接能處理得更快,而是在於能處理更多的連接。


信號I/O(Signal-Driven I/O Model)

在這裏插入圖片描述

魚竿掛個鈴,丟下去,等鈴響了就收竿了。


異步I/O(Asynchronous I/O Model)

在這裏插入圖片描述

魚竿丟下去,僱個小弟在那幫我看,釣到了,打電話告訴我魚釣了,然後回去收魚。

異步I/O根據POSIX標準定義。

應用程序呼叫aio_read(POSIX異步I/O方法用aio_或lio_開頭)。系統會馬上返回並且應用程序沒有被阻塞,而是繼續執行。等到kernel準備好數據,並且拷貝到應用程序的緩衝區後,會給應用程序數據一個signal(應用程序通常告訴kernel怎麼通知),告訴應用程序read操作已經好了。

和信號驅動I/O不同的是,異步I/O的應用程序整個進程都不會被阻塞,kernel拷貝好數據後,通知應用程序。而信號驅動,只是在數據可讀後通知應用程序,還要再呼叫recvfrom去讓kernel拷貝數據。


比較

blocking I/O vs nonblocking I/O

blocking:阻塞式I/O,非阻塞式I/O,I/O複用,信號驅動I/O

nonblocking:異步I/O

blocking IO會一直block住對應的進程知道相應操作完成,而nonblocking IO會在kernel還在準備數據的時候就返回,繼續執行。

asynchronous I/O vs synchronous I/O

synchronous:阻塞式I/O,非阻塞式I/O,I/O複用,信號驅動I/O

asynchronous :異步I/O

POSIX對這兩個名詞的定義是:

  • 一個同步I/O操作會導致進程阻塞直到該I/O操作完成
    A synchronous I/O operation causes the requesting process to be blocked until that
    I/O operation completes.
  • 一個異步I/O操作不會導致進程被阻塞
    An asynchronous I/O operation does not cause the requesting process to be blocked.

在這裏插入圖片描述


資料來源

<<UNIX Network Programming(Volume1,3rd)>> 6.2章

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章