Java NIO 之 I/O基本概念(二)

內存映射文件

傳統的文件 I/O 是通過用戶進程發佈 read( )write( )系統調用來傳輸數據的。爲了在內核空間的文件系統頁與用戶空間的內存區之間移動數據,一次以上的拷貝操作幾乎總是免不了的。這是因爲,在文件系統頁與用戶緩衝區之間往往沒有一一對應關係。但是,還有一種大多數操作系統都支持的特殊類型的 I/O 操作,允許用戶進程最大限度地利用面向頁的系統 I/O 特性,並完全摒棄緩衝區拷貝。這就是內存映射 I/O.內存映射 I/O 使用文件系統建立從用戶空間直到可用文件系統頁的虛擬內存映射。這樣做有幾個好處:

用戶進程把文件數據當作內存,所以無需發佈 read( )write( )系統調用。
當用戶進程碰觸到映射內存空間,頁錯誤會自動產生,從而將文件數據從磁盤讀進內存。如果用戶修改了映射內存空間,相關頁會自動標記爲髒,隨後刷新到磁盤,文件得到更新。
操作系統的虛擬內存子系統會對頁進行智能高速緩存,自動根據系統負載進行內存管理。
數據總是按頁對齊的,無需執行緩衝區拷貝。
大型文件使用映射,無需耗費大量內存,即可進行數據拷貝。
虛擬內存和磁盤 I/O 是緊密關聯的,從很多方面看來,它們只是同一件事物的兩面。在處理大量數據時,尤其要記得這一點。如果數據緩衝區是按頁對齊的,且大小是內建頁大小的倍數,那麼,對大多數操作系統而言,其處理效率會大幅提升。


文件鎖定

文件鎖定機制允許一個進程阻止其他進程存取某文件,或限制其存取方式。通常的用途是控制共享信息的更新方式,或用於事務隔離。在控制多個實體並行訪問共同資源方面,文件鎖定是必不可少的。數據庫等複雜應用嚴重信賴於文件鎖定。
文件鎖定從字面上看有鎖定整個文件的意思(通常的確是那樣),但鎖定往往可以發生在更爲細微的層面,鎖定區域往往可以細緻到單個字節。鎖定與特定文件相關,開始於文件的某個特定字節地址,包含特定數量的連續字節。這對於協調多個進程互不影響地訪問文件不同區域,是至關重要的。
文件鎖定有兩種方式:共享的和獨佔的。多個共享鎖可同時對同一文件區域發生作用;獨佔鎖則不同,它要求相關區域不能有其他鎖定在起作用。
共享鎖和獨佔鎖的經典應用,是控制最初用於讀取的共享文件的更新。某個進程要讀取文件,會先取得該文件或該文件部分區域的共享鎖。第二個希望讀取相同文件區域的進程也會請求共享鎖。兩個進程可以並行讀取,互不影響。但是,假如有第三個進程要更新該文件,它會請求獨佔鎖。該進程會處於阻滯狀態,直到既有鎖定(共享的、獨佔的)全部解除。一旦給予獨佔鎖,其他共享鎖的讀取進程會處於阻滯狀態,直到獨佔鎖解除。這樣,更新進程可以更改文件,而其他讀取進程不會因爲文件的更改得到前後不一致的結果。

文件鎖有建議使用和強制使用之分。建議型文件鎖會向提出請求的進程提供當前鎖定信息,但操作系統並不要求一定這樣做,而是由相關進程進行協調並關注鎖定信息。多數 Unix 和類 Unix 作系統使用建議型鎖,有些也使用強制型鎖或兼而有之。強制型鎖由操作系統或文件系統強行實施,不管進程對鎖的存在知道與否,都會阻止其對文件鎖定區域的訪問。微軟的操作系統往往使用的是強制型鎖。假定所有文件鎖均爲建議型,並在訪問共同資源的各個應用程序間使用一致的文件鎖定,是明智之舉,也是唯一可行的跨平臺策略。依賴於強制文件鎖定的應用程序,從根子上講就是不可移植的。


I/O

並非所有 I/O 都像前幾節講的是面向塊的,也有流 I/O,其原理模仿了通道。 I/O 字節流必須順序存取,常見的例子有 TTY(控制檯)設備、打印機端口和網絡連接。
流的傳輸一般(也不必然如此)比塊設備慢,經常用於間歇性輸入。多數操作系統允許把流置於非塊模式,這樣,進程可以查看流上是否有輸入,即便當時沒有也不影響它幹別的。這樣一種能力使得進程可以在有輸入的時候進行處理, 輸入流閒置的時候執行其他功能。比非塊模式再進一步,就是就緒性選擇。就緒性選擇與非塊模式類似(常常就是建立在非塊模式之上),但是把查看流是否就緒的任務交給了操作系統。操作系統受命查看一系列流,並提醒進程哪些流已經就緒。這樣,僅僅憑藉操作系統返回的就緒信息,進程就可以使用相同代碼和單一線程,實現多活動流的多路傳輸。這一技術廣泛用於網絡服務器領域,用來處理數量龐大的網絡連接。就緒性選擇在大容量縮放方面是必不可少的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章