13.6 繞過緩衝區快取記憶體:直接i/o
始於核心2.4,linux允許應用程式在執行磁碟i/o時繞過緩衝區快取記憶體,從使用者空間直接將資料傳遞到檔案或磁碟裝置。有時也稱此為直接i/o(direct i/o)或者裸i/o(raw i/o)。
此處的描述細節為linux所特有,susv3並未對其進行規範。儘管如此,大多數unix實現均對裝置和檔案提供了某種形式的直接i/o訪問。
有時會將直接i/o誤認為獲取快速i/o效能的一種手段。然而,對於大多數應用而言,使用直接i/o可能會大大降低效能。這是因為為了提高i/o效能,
核心針對緩衝區快取記憶體做了不少優化,其中包括:按順序預讀取,在成簇(clusters)磁碟塊上執行i/o,允許訪問同一檔案的多個程序共享快取記憶體的緩衝區。
應用如使用了直接i/o將無法受益於這些優化舉措。直接i/o只適用於有特定i/o需求的應用。例如資料庫系統,其快取記憶體和i/o優化機制均自成一體,無需核心消耗cpu時間和記憶體去完成相同任務。
可針對乙個單獨檔案或塊裝置(比如,一塊磁碟)執行直接i/o。要做到這點,需要在呼叫open()開啟檔案或裝置時指定o_direct標誌。
o_direct標誌自核心2.4.10開始有效,並非所有linux檔案系統和核心版本都支援該標誌。絕大多數原生(native)檔案系統都支援o_direct,但許多非unix檔案系統(比如vfat)則不支援。對於所關注的檔案系統,有必要進行相關測試(若檔案系統不支援o_direct,則open()將失敗並返回錯誤號einval)或是閱讀核心原始碼,以此來加以驗證。
若一程序以o_direct標誌開啟某檔案,而另一程序以普通方式(即使用了快取記憶體緩衝區)開啟同一檔案,則由直接i/o所讀寫的資料與緩衝區快取記憶體中內容之間不存在一致性。應盡量避免這一場景。
raw(8)手冊頁描述了乙個獲取對磁碟裝置進行原始訪問的老技術(現在已過時)。
直接i/o的對齊限制
因為直接i/o(針對磁碟裝置和檔案)涉及對磁碟的直接訪問,所以在執行i/o時,必須遵守一些限制。
用於傳遞資料的緩衝區,其記憶體邊界必須對齊為塊大小的整數倍。
資料傳輸的開始點,亦即檔案和裝置的偏移量,必須是塊大小的整數倍。
待傳遞資料的長度必須是塊大小的整數倍。
不遵守上述任一限制均將導致einval錯誤。在上述列表中,塊大小(block size)指裝置的物理塊大小(通常為512位元組)。
當執行直接i/o時,linux 2.4比linux 2.6限制更為嚴格:對齊、長度及偏移量必須是底層檔案系統邏輯塊大小的整數倍。(典型檔案系統的邏輯塊大小為1024、2048或4096位元組。)
示例程式
程式清單13-1提供了乙個使用o_direct標誌開啟乙個檔案讀取資料的簡單例子。該程式可指定多達4個命令列引數,依次為要讀取的檔案、要從檔案中讀取的位元組數、讀之前在檔案中定位(seek)的偏移量和傳遞給read()的資料緩衝區對齊。最後兩個為可選引數,預設值分別為0位元組和4096位元組。下面是執行該程式的一些示例:
程式清單13-1中程式使用memalign()函式來分配一塊記憶體,其記憶體塊與第乙個引數的整數倍對齊。7.1.4節對memalign()函式有所描述。
程式清單13-1:使用o_direct跳過緩衝區快取記憶體
快取記憶體與緩衝區
作業系統中使用磁碟快取記憶體技術來提高磁碟的i o速度,對快取記憶體複製的訪問要比原始資料訪問更為高效。例如,正在執行的程序的指令既儲存在磁碟上,也儲存在物理記憶體上,也被複製到cpu的二級和一級快取記憶體中。不過,磁碟快取記憶體技術不同於通常意義下的介於cpu與記憶體之間的小容量高速儲存器,而是指...
緩衝區 快取
快取 cache 所以兩個的區別 緩衝區是記憶體空間的一部分 用來緩衝輸入和輸出的資料 緩衝區具有一部分大小 緩衝區根據對應的是輸入裝置還是輸出裝置分為輸入緩衝區,輸出緩衝區 buffer的核心作用是用來緩衝,緩和衝擊。比如你每秒要寫100次硬碟,對系統衝擊很大,浪費了大量時間在忙著處理開始寫和結束...
緩衝區(1) 為什麼會有緩衝區(快取)?
緩衝區是為了讓低速的輸入輸出裝置和高速的使用者程式能夠協調工作,並降低輸入輸出裝置的讀寫次數。使用者程式的執行速度可以看做 cpu 的執行速度,如果沒有各種硬體的阻礙,理論上它們是同步的。例如,我們都知道硬碟的速度要遠低於 cpu,它們之間有好幾個數量級的差距,當向硬碟寫入資料時,程式需要等待,不能...