對於IO訪問(例如,讀取),數據將首先復制到操作系統內核的緩沖區,然後復制到應用程序的地址空間。
因此,當讀操作發生時,它將經歷兩個階段。
正是因為這兩個階段,linux系統產生了以下五種網絡模式:
在linux下,默認情況下所有的socket都是阻塞的,過程如下圖所示:
進程調用recvfrom系統調用來讀取數據,這意味著如果數據還沒有到達,進程將進入阻塞狀態。數據到了就拷貝到內核,再從內核拷貝到用戶空間,用戶進程就暢通了。
特性:進程在IO執行的兩個階段都會被阻塞。
在執行非阻塞io系統調用時,如果內核中的數據沒有準備好,會直接返回,不會阻塞。通過不斷查詢的過程,直到數據在內核中準備好,才開始復制到用戶空間。在復制的過程中,進程仍然是阻塞的,所有非阻塞的IO都是同步IO。
特點:進程需要不斷詢問內核數據是否準備好。
單個進程處理多個網絡連接IO,並使用三個系統調用select\poll\epoll來連續輪詢所有連接,如果數據到達內核則通知進程,並將數據復制到用戶的內存中。
當調用select時,進程將進入阻塞狀態,直到數據到達。
這個圖看起來與阻塞IO沒有什麽不同,甚至使用了壹個額外的系統調用。
但它的優點是可以同時監控多個IO連接。
所以如果連接數不是很高的話,使用select/epoll的web服務器性能不壹定比使用多線程+阻塞IO的web服務器好。多路IO復用的優勢不在於可以更快的處理單個連接,而在於可以處理更多的連接。
linux下的異步io很少使用,其流程如下:
讀操作發起後,進程立即返回,整個Io進程不會產生任何塊。內核將等待數據準備好,然後將數據復制到用戶的內存中。當所有這些都完成後,內核將向用戶進程發送壹個信號,告訴它讀操作已經完成。
調用阻塞io將阻塞進程,直到操作完成。
當內核準備數據時,無阻塞io將立即返回。
只有異步IO才是異步IO,
其他三種:阻塞IO、非阻塞IO、復用IO都是同步的。
這是因為其他三個IO在執行真實IO操作的過程中有進程阻塞階段,而異步IO的進程在整個過程中沒有阻塞。當內核數據準備好並復制到用戶空間時,非阻塞IO也是阻塞的,因此它也是同步IO。
Linux IO模式以及select、poll和epoll的詳細說明