Linux裏五種I/O模型

阻塞I/O

如上圖,咱們寫的應用程序使用數據流(UDP)Socket接收數據,調用recvfrom()系統函數接收網卡上的數據。在阻塞I/O下,調用recvfrom()將形成進程阻塞,直到數據接收完畢。異步

內存空間有系統空間和用戶空間,而且都有相應的緩衝區:async

  • 第一階段(wait for data等待數據準備):進程阻塞,內核接管,複製數據到系統空間裏的數據緩衝區(固然是可以從網卡上接收到數據)。接收完畢後,則數據準備完畢(datagram ready)。
  • 第二階段(copy data from kernel to user從內核拷貝數據到用戶緩衝區):這時候進程仍然阻塞,內核將系統空間內緩衝區ready的數據複製到用戶空間裏的用戶本身定義的緩衝區。拷貝完畢則喚醒進程。 整個階段,進程都是阻塞的,直到數據讀取到用戶緩衝區內。

非阻塞I/O

如上圖,一樣應用程序調用數據流(UDP)Socket接收數據,調用recvfrom()系統函數,而且設置了Socket爲non-blocking非阻塞。函數

這時咱們調用系統函數recvfrom()則不阻塞進程,若是數據沒有在系統空間的緩衝區內準備好,則當即返回一個error,直接獲得一個結果,這時候進程能夠作點其餘任務而不用阻塞在這裏。可是若是數據在系統空間內的緩衝區準備好了,則將開始從系統空間拷貝數據到用戶空間。操作系統

I/O 多路複用(IO multiplexing)

I/O多路複用大體狀況如上圖。I/O多路複用也就是咱們常說的select、poll以及epoll,它可以使一個進程可以同時處理更多的鏈接。指針

這裏就以select爲例:select()也是一個系統調用,若是一個進程調用了select()那麼這個進程也會被阻塞。code

  • 第一階段:應用程序進程調用select(),這時該進程阻塞,不過內核會監視應用程序向select註冊的全部Socket。若是註冊的Socket中有數據以及在系統空間緩衝區裏準備好了的,則該進程被喚醒。
  • 第二階段:從select()的阻塞中返回,應用程序進程只能知道向select註冊的Socket裏有數據準備好的Socket,可是並不知道具體是哪一個Socket數據準備好了。因此,應用程序須要本身遍歷Socket,找出數據準備好的Socket,而後調用recvfrom()函數將系統空間緩衝區內數據複製到用戶空間緩衝區內。

信號驅動 I/O(signal driven IO)

Linux內核定義了不少信號,如SIGUSR1和SIGUSR2都是能夠用戶自定義發送/處理的信號。cdn

應用程序首先須要安裝信號處理器(即提供一個回調函數給內核),當相應事件發生的時候,操做系統會激活該信號,處理權交給進程,由進程調用處理該信號的回調函數。blog

在信號驅動I/O中,應用程序先安裝信號處理器,返回結果,進程能夠繼續執行。當數據在系統空間內準備好了後,內核會激活信號,進程則會調用相應的回調函數(這裏數據準備好了則直接調用recvfrom()函數),而後數據則直接拷貝到用戶空間緩衝區內。進程

異步 I/O(asynchronous IO)

異步I/O則是調用aio_read()系統函數,傳入了用戶空間緩衝區的地址指針。調用後進程不會被阻塞,則能夠作其餘事情,內核會在將數據複製到系統空間緩衝區,而後再將數據複製到用戶提供的用戶緩衝區地址中。都作完了後,則內核發送一個signal通知應用程序read完成了。這時應用程序以前提供的回調函數,由該進程來執行。事件

相關文章
相關標籤/搜索