IO概念和五種IO模型


一、什么是IO?

我們都知道unix世界里、一切皆文件、而文件是什么呢?文件就是一串二進制流而已、不管socket、還是FIFO、管道、終端、對我們來說、一切都是文件、一切都是流、在信息交換的過程中、我們都是對這些流進行數據的收發操作、簡稱為I/O操作(input and output)、往流中讀出數據、系統調用read、寫入數據、系統調用write、不過話說回來了、計算機里有這么多的流、我怎么知道要操作哪個流呢?做到這個的就是文件描述符、即通常所說的fd、一個fd就是一個整數、所以對這個整數的操作、就是對這個文件(流)的操作、我們創建一個socket、通過系統調用會返回一個文件描述符、那么剩下對socket的操作就會轉化為對這個描述符的操作、不能不說這又是一種分層和抽象的思想。

二、IO交互

通常用戶進程中的一個完整IO分為兩個階段:

 

 用戶空間<------------->內核空間、

 內核空間<------------->設備空間、

 

 內核空間中存放的是內核代碼和數據、而進程的用戶空間中存放的是用戶程序的代碼和數據、不管是內核空間還是用戶空間、它們都處於虛擬空間中、Linux使用兩級保護機制:0級供內核使用、3級供用戶程序使用、

 操作系統和驅動程序運行在內核空間、應用程序運行在用戶空間、兩者不能簡單地使用指針傳遞數據、因為Linux使用的虛擬內存機制、其必須通過系統調用請求kernel來協助完成IO動作、內核會為每個IO設備維護一個緩沖區、用戶空間的數據可能被換出、當內核空  間使用用戶空間指針時、對應的數據可能不在內存中

對於一個輸入操作來說、進程IO系統調用后、內核會先看緩沖區中有沒有相應的緩存數據、沒有的話再到設備中讀取、因為設備IO一般速度較慢、需要等待、內核緩沖區有數據則直接復制到進程空間、

所以、對於一個網絡輸入操作通常包括兩個不同階段:

(1)等待網絡數據到達網卡 –&gt; 讀取到內核緩沖區

(2)從內核緩沖區復制數據 –&gt; 用戶空間

IO有內存IO、網絡IO和磁盤IO三種、通常我們說的IO指的是后兩者

 

1.阻塞IO(blocking I/O)

A拿着一支魚竿在河邊釣魚,並且一直在魚竿前等,在等的時候不做其他的事情,十分專心。只有魚上鈎的時,才結束掉等的動作,把魚釣上來。

在內核將數據准備好之前,系統調用會一直等待所有的套接字,默認的是阻塞方式。 

 其實,我們例子中所說的魚竿就是這一個文件描述符。這個模型是我們最常見的,程序調用和我們編寫的基本程序是一致的。

fd=connect();
write(fd);
read(fd);
close(fd);

  

程序的read必須在write之后執行,當write阻塞住了,read就不能執行下去,一直處於等待狀態。

2.非阻塞IO(noblocking I/O)
B也在河邊釣魚,但是B不想將自己的所有時間都花費在釣魚上,在等魚上鈎這個時間段中,B也在做其他的事情(一會看看書,一會讀讀報紙,一會又去看其他人的釣魚等),但B在做這些事情的時候,每隔一個固定的時間檢查魚是否上鈎。一旦檢查到有魚上鈎,就停下手中的事情,把魚釣上來。

其實,B在檢查魚竿是否有魚,是一個輪詢的過程。

每次客戶詢問內核是否有數據准備好,即文件描述符緩沖區是否就緒。當有數據報准備好時,就進行拷貝數據報的操作。當沒有數據報准備好時,也不阻塞程序,內核直接返回未准備就緒的信號,等待用戶程序的下一個輪尋。

但是,輪尋對於CPU來說是較大的浪費,一般只有在特定的場景下才使用。

3.信號驅動IO(signal blocking I/O)
C也在河邊釣魚,但與A、B不同的是,C比較聰明,他給魚竿上掛一個鈴鐺,當有魚上鈎的時候,這個鈴鐺就會被碰響,C就會將魚釣上來。

信號驅動IO模型,應用進程告訴內核:當數據報准備好的時候,給我發送一個信號,對SIGIO信號進行捕捉,並且調用我的信號處理函數來獲取數據報。

4.IO多路復用(I/O multiplexing)
D同樣也在河邊釣魚,但是D生活水平比較好,D拿了很多的魚竿,一次性有很多魚竿在等,D不斷的查看每個魚竿是否有魚上鈎。增加了效率,減少了等待的時間。

IO多路轉接是多了一個select函數,select函數有一個參數是文件描述符集合,對這些文件描述符進行循環監聽,當某個文件描述符就緒時,就對這個文件描述符進行處理。

其中,select只負責等,recvfrom只負責拷貝。
IO多路轉接是屬於阻塞IO,但可以對多個文件描述符進行阻塞監聽,所以效率較阻塞IO的高。

5.異步IO(asynchronous I/O)
E也想釣魚,但E有事情,於是他雇來了F,讓F幫他等待魚上鈎,一旦有魚上鈎,F就打電話給E,E就會將魚釣上去。

當應用程序調用aio_read時,內核一方面去取數據報內容返回,另一方面將程序控制權還給應用進程,應用進程繼續處理其他事情,是一種非阻塞的狀態。

當內核中有數據報就緒時,由內核將數據報拷貝到應用程序中,返回aio_read中定義好的函數處理程序。

很少有Linux系統支持,Windows的IOCP就是該模型。

可以看出,阻塞程度:阻塞IO>非阻塞IO>多路轉接IO>信號驅動IO>異步IO,效率是由低到高的。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM