1. 程式人生 > >Java NIO筆記之IO基礎概念

Java NIO筆記之IO基礎概念

1.緩衝區
緩衝區是所有IO的基礎,”輸入/輸出”就是將資料移進或移除緩衝區。程序IO操作的執行也是向作業系統傳送請求,讓它要麼將緩衝區的資料排幹(寫),要麼將緩衝區的填滿資料(讀)。
這裡寫圖片描述
圖 1-1 簡單描述了資料從外部磁碟向執行中的程序的記憶體區域移動的過程。程序使用 read()系統呼叫,要求其緩衝區被填滿。核心隨即向磁碟控制硬體發出命令,要求其從磁碟讀取資料。磁碟控制器把資料直接寫入核心記憶體緩衝區,這一步通過 DMA 完成,無需主CPU協助。一旦磁碟控制器把緩衝區裝滿,核心即把資料從核心空間的臨時緩衝區拷貝到程序執行read()呼叫時指定的緩衝區。
2.使用者空間和系統空間
這裡寫圖片描述


  使用者空間是常規程序所在區域。JVM 就是常規程序,駐守於使用者空間。使用者空間是非特權區域:比如,在該區域執行的程式碼就不能直接訪問硬體裝置。
  核心空間是作業系統所在區域。核心程式碼有特別的權力:它能與裝置控制器通訊,控制著使用者區域程序的執行狀態,等等。最重要的是,所有I/O都直接或間接通過核心空間。

  當程序請求I/O操作的時候,它執行一個系統呼叫(有時稱為陷阱)將控制權移交給核心。C/C++程式設計師所熟知的底層函式open()、read()、write()和close()要做的無非就是建立和執行適當的系統呼叫。當核心以這種方式被呼叫,它隨即採取任何必要步驟,找到程序所需資料,並把資料傳送到使用者空間內的指定緩衝區。核心試圖對資料進行快取記憶體或預讀取,因此程序所需資料可能已經在核心空間裡了。如果是這樣,該資料只需簡單地拷貝出來即可。如果資料不在核心空間,則程序被掛起,核心著手把資料讀進記憶體。

  您可能會覺得,把資料從核心空間拷貝到使用者空間似乎有些多餘。為什麼不直接讓磁碟控制器把資料送到使用者空間的緩衝區呢?
這樣做有幾個問題。
首先,硬體通常不能直接訪問使用者空間 其次,像磁碟這樣基於塊儲存的硬體裝置操作的是固定大小的資料塊,而使用者程序請求的可能是任意大小的或非對齊的資料塊。在資料往來於使用者空間與儲存裝置的過程中,核心負責資料的分解、再組合工作,因此充當著中間人的角色。
3.虛擬記憶體
虛擬記憶體意為使用虛假(或虛擬)地址取代物理(硬體RAM)記憶體地址
(1)一個以上的虛擬地址可指向同一個實體記憶體地址.
(2)虛擬記憶體空間可大於實際可用的硬體記憶體.
  裝置控制器不能通過DMA直接儲存到使用者空間,但通過利用上面提到的第一項,則可以達到相同效果。把核心空間地址與使用者空間的虛擬地址對映到同一個實體地址,這樣,DMA 硬體(只能訪問實體記憶體地址)就可以填充對核心與使用者空間程序同時可見的緩衝區(見圖1-3)。
4.記憶體頁面排程
這裡寫圖片描述


  為了支援虛擬記憶體的第二個特性(定址空間大於實體記憶體),就必須進行虛擬記憶體分頁(經常稱為交換,雖然真正的交換是在程序層面完成,而非頁層面)。依照該方案,虛擬記憶體空間的頁面能夠繼續存在於外部磁碟儲存,這樣就為實體記憶體中的其他虛擬頁面騰出了空間。從本質上說,實體記憶體充當了分頁區的快取記憶體;而所謂分頁區,即從實體記憶體置換出來,轉而儲存於磁碟上的記憶體頁面。
  現代CPU包含一個稱為記憶體管理單元(MMU)的子系統,邏輯上位於CPU與實體記憶體之間。該裝置包含虛擬地址向實體記憶體地址轉換時所需對映資訊。當CPU引用某記憶體地址時,MMU負責確定該地址所在頁(往往通過對地址值進行移位或遮蔽位操作實現),並將虛擬頁號轉換為物理頁號(這一步由硬體完成,速度極快)。如果當前不存在與該虛擬頁形成有效對映的實體記憶體頁,MMU會向CPU 提交一個頁錯誤。
5.檔案IO
  檔案系統是更高層次的抽象,是安排、解釋磁碟(或其他隨機存取塊裝置)資料的一種獨特方式。您所寫程式碼幾乎無一例外地要與檔案系統打交道,而不是直接與磁碟打交道。是檔案系統定義了檔名、路徑、檔案、檔案屬性等抽象概念。
  所有I/O都是通過請求頁面排程完成的。頁面排程是非常底層的操作,僅發生於磁碟扇區與記憶體頁之間的直接傳輸。而檔案 I/O 則可以任意大小、任意定位。那麼,底層的頁面排程是如何轉換為檔案 I/O 的?
  檔案系統把一連串大小一致的資料塊組織到一起。有些塊儲存元資訊,如空閒塊、目錄、索引等的對映,有些包含檔案資料。單個檔案的元資訊描述了哪些塊包含檔案資料、資料在哪裡結束、最後一次更新是什麼時候,等等。
  當用戶程序請求讀取檔案資料時,檔案系統需要確定資料具體在磁碟什麼位置,然後著手把相關磁碟扇區讀進記憶體。老式的作業系統往往直接向磁碟驅動器釋出命令,要求其讀取所需磁碟扇區。而採用分頁技術的現代作業系統則利用請求頁面排程取得所需資料。
採用分頁技術的作業系統執行 I/O 的全過程可總結為以下幾步:
1、確定請求的資料分佈在檔案系統的哪些頁(磁碟扇區組)。磁碟上的檔案內容和元資料可能跨越多個檔案系統頁,而且這些頁可能也不連續。
2、在核心空間分配足夠數量的記憶體頁,以容納得到確定的檔案系統頁。
3、在記憶體頁與磁碟上的檔案系統頁之間建立對映。
4、為每一個記憶體頁產生頁錯誤。
5、虛擬記憶體系統俘獲頁錯誤,安排頁面調入,從磁碟上讀取頁內容,使頁有效。
6、一旦頁面調入操作完成,檔案系統即對原始資料進行解析,取得所需檔案內容或屬性資訊。
  需要注意的是,這些檔案系統資料也會同其他記憶體頁一樣得到快取記憶體。對於隨後發生的 I/O請求,檔案資料的部分或全部可能仍舊位於實體記憶體當中,無需再從磁碟讀取即可重複使用。
6.對映記憶體檔案
這裡寫圖片描述
記憶體對映I/O使用檔案系統建立從使用者空間直到可用檔案系統頁的虛擬記憶體對映。這樣做有幾
個好處:
1、使用者程序把檔案資料當作記憶體,所以無需釋出 read( )或 write( )系統呼叫。
2、當用戶程序碰觸到對映記憶體空間,頁錯誤會自動產生,從而將檔案資料從磁碟讀進記憶體。如果使用者修改了對映記憶體空間,相關頁會自動標記為髒,隨後重新整理到磁碟,檔案得到更新。
3、作業系統的虛擬記憶體子系統會對頁進行智慧快取記憶體,自動根據系統負載進行記憶體管理。
4、資料總是按頁對齊的,無需執行緩衝區拷貝。
5、大型檔案使用對映,無需耗費大量記憶體,即可進行資料拷貝。
虛擬記憶體和磁碟 I/O 是緊密關聯的,從很多方面看來,它們只是同一件事物的兩面。在處理大量資料時,尤其要記得這一點。如果資料緩衝區是按頁對齊的,且大小是內建頁大小的倍數,那麼,對大多數作業系統而言,其處理效率會大幅提升。
7.檔案鎖定
這裡寫圖片描述
這裡寫圖片描述
檔案鎖定有兩種方式:共享的和獨佔的。多個共享鎖可同時對同一檔案區域發生作用;獨佔鎖則不同,它要求相關區域不能有其他鎖定在起作用。

參考:《Java NIO》