本文的背景是Linux環境下的network IO。
五大IO模型
當 IO 發生時涉及的對象和步驟:
對於一個網絡 IO 它會涉及到兩個系統對象,一個是調用這個 IO 的進程(或線程)另一個就是系統內核(kernel)。它會經歷兩個階段:
- 等待數據準備
- 將數據從內核拷貝到進程中
如果要想提高IO效率,需要將等的時間降低。
一、同步阻塞IO(blocking I/O)
在linux中,默認情況下所有的socket都是blocking。
內核將數據準備好之前,進程會一直阻塞,直到數據拷貝完成。 可以理解爲:A拿一根魚竿去釣魚,並且一直在魚竿前等於上鉤。
二、同步非阻塞IO(noblocking I/O)
Linux下,可以通過設置socket使其變爲non-blocking。
非阻塞IO通過進程反覆調用IO函數(多次系統調用,並馬上返回);在數據拷貝的過程中,進程是阻塞的。 可以理解爲:B也在釣魚,但是他每隔固定時間去查看是否有魚上鉤。
三、多路複用IO(IO multiplexing)
I/O是指網絡I/O,多路指多個TCP連接(即socket或者channel),複用指複用一個或幾個線程。意思說一個或一組線程處理多個連接。
Linux下,通過 select/poll/epoll 函數對一個IO端口多次調用,select/poll/epoll這三個函數會不斷的輪詢所負責的所有socket,當某個socket有數據到達了,就通知用戶進程。 可以理解爲:C拿了很多根魚竿去釣魚,並且不斷的查看每個魚竿是否有魚上鉤。增加了效率。
四、信號驅動IO(signal blocking I/O)
首先我們允許套接口進行信號驅動I/O,並安裝一個信號處理函數,進程繼續運行並不阻塞。當數據準備好時,進程會收到一個SIGIO信號,可以在信號處理函數中調用I/O操作函數處理數據。 可以理解爲:D來釣魚,但是他在魚竿上綁了一個鈴鐺,當有魚上鉤的時候,鈴鐺就會響,D就會把魚釣上來。
五、異步IO(Asynchronous I/O)
Linux下的asynchronous IO其實用得不多,從內核2.6版本纔開始引入。
當一個異步過程調用發出後,調用者不能立刻得到結果。實際處理這個調用的部件在完成後,通過狀態、通知和回調來通知調用者的輸入輸出操作。 可以理解爲:E也來釣魚,但是他僱了一個人來幫他看魚竿,自己去做別的事情,當有魚上鉤時再通知他來取魚。
總結:
五種IO的模型:阻塞IO、非阻塞IO、多路複用IO、信號驅動IO和異步IO;前四種都是同步IO,在內核數據copy到用戶空間時都是阻塞的。
阻塞程度:阻塞IO>非阻塞IO>多路轉接IO>信號驅動IO>異步IO,效率是由低到高的