#
Linux檔案系統作為作業系統的核心組成部分,其運行機制也是我們程式設計師需要了解和掌握的,磁碟為系統提供了最基本的持久化存儲,檔案系統則在磁碟的基礎上提供系統裡所有文件的管理,在Linux裡一切皆文件,不僅普通的文件和目錄,就連塊設備、套接字、管道等,也都要透過統一的文件系統來管理。今天我們就一起來聊聊:磁碟和檔案系統是怎麼運作的?
索引節點與目錄項目
#在Linux檔案系統中,一個檔案的元資料包括:目錄項目、索引節點、資料區塊。
- 目錄項目:簡稱為dentry,用來記錄檔案的名字、索引節點指標、與其他目錄項目的關聯關係。多個關聯的目錄項,就構成了檔案系統的目錄結構。目錄項目是由核心維護的一個記憶體資料結構,所以通常也被叫做目錄項目快取(Cache)。
- 索引節點:簡稱為inode,用來記錄檔案的元數據,包括inode 編號、檔案大小、存取權限、修改日期、資料的位置、連結數等,索引節點資訊會持久化到磁碟中存儲,佔用磁碟空間。
- 資料塊: 簡稱為block,儲存檔案資料的地方。磁碟的最小儲存單位叫做磁區(Sector),每個磁區儲存512位元組,相當於0.5KB,作業系統讀取硬碟的時候,不會一個磁區一個磁區讀取,這樣效率太低,而是一次連續讀取多個磁區,即一次讀取一個」區塊」(block)。這種由多個磁區組成的”區塊”,是檔案存取的最小單位。 「塊」的大小,最常見的是4KB(八個sector)。
為了加速檔案訪問,索引節點通常會被載入到記憶體中,而硬碟在格式化時會劃分為超級區塊、索引節點區和資料區塊區三個儲存區域。
- 超級區塊,用來儲存檔案系統的詳細信息,例如區塊個數、區塊大小、空閒區塊等等。
- 索引節點區,用來儲存索引節點。
- 資料塊區,用來儲存檔案或目錄資料。
虛擬檔案系統
Linux系統的虛擬文件系統(VFS,Virtual File System)是一個關鍵的抽象層,它為用戶和應用程式提供了一致的文件系統接口,讓它們可以以統一的方式訪問各種類型的文件系統,而無需擔心底層檔案系統的實作細節。
使用者程式和 glibc 函式庫都屬於使用者空間,透過呼叫系統呼叫層(SCI)的函數來完成檔案操作。這些函數是 Linux 核心提供的接口,用於使用者向系統請求操作。例如,系統中的cat指令會呼叫open()函數開啟文件,然後呼叫read()函數讀取檔案內容,最後呼叫write()函數將檔案內容輸出到控制台。常見的檔案系統類型可分為幾大類。
- 基於本機磁碟:EXT3、EXT4、XFS、OverlayFS 等。這類檔案系統的特色是資料直接儲存在電腦本機掛載的磁碟中,效能好,沒有網路IO的存取消耗。
- 基於網路檔案系統:NFS、CIFS/SMB、CephFS、GlusterFS等,這類檔案的特點是它們允許使用者透過網路存取和管理檔案。分散式、跨平台、靈活性和可擴充性是它們的最大優勢。
- 基於記憶體檔案系統:tmpfs、ramfs、/proc等,這些基於記憶體的檔案系統通常用於特定的用途,如臨時檔案儲存、快取、快速資料存取等。它們提供了在記憶體中進行文件讀寫操作的高效能解決方案,但也需要注意記憶體限制和資料易失性的特性。
檔案 I/O
#我們進行磁碟分割和格式化是為了建立不同類型的檔案系統,這些檔案系統必須透過掛載到Linux的VFS上的特定目錄才能被系統使用。文件的讀寫操作有不同的I/O類型,應用程式根據需要選擇適當的方式進行。
緩衝與非緩衝I/O
- 所謂不帶緩衝,並不是指內核不提供緩衝,而是只單純的系統調用,不是函數庫的調用。系統核心對磁碟的讀寫都會提供一個區塊緩衝,當用write函數對其寫資料時,直接調用系統調用,將資料寫入到區塊緩衝進行排隊,當區塊緩衝達到一定的量時,才會把資料寫入磁碟。因此所謂的不帶緩衝的I/O是指進程不提供緩衝功能。每調用一次write或read函數,直接系統調用。 (內核提供緩衝的)。
- 而帶緩衝的I/O是指進程對輸入輸出流進行了改進,提供了一個流緩衝。當用write函數寫資料時,先把資料寫入流緩衝區中,當達到一定條件,例如流緩衝區滿了,這時候才會把資料一次送到核心提供的區塊緩衝,再經區塊緩衝寫入磁碟。 (雙重緩衝)
- 因此,有緩衝的I/O在寫入相同的資料量到磁碟時,會比沒有緩衝的I/O呼叫系統呼叫的次數少。
直接 I/O與非直接I/O
- 直接I/O:就是應用程式直接存取磁碟數據,而不經過核心緩衝區,這樣做的目的是減少一次從核心緩衝區到使用者程式快取的資料複製。
- 非直接I/O:就是檔案讀寫時,先要經過系統的頁緩存,然後再由核心或額外的系統呼叫後寫入磁碟。
- 對於直接I/O,如果存取的資料不在應用程式快取中,那麼每次資料都會直接從磁碟加載,這種直接加載的效率會比較慢。但是類型於資料庫管理系統這類應用,它們更傾向於選擇它們自己的快取機制,因為資料庫管理系統往往比作業系統更了解資料庫中存放的數據,使用直接I/O更合適。
阻塞I/O和非阻塞I/O
- #阻塞I/O:應用程式呼叫I/O操作時阻塞,只有等待要操作的資料準備好,並複製到應用程式的緩衝區中才回傳。特點是:實現難度低、開發應用較容易,適用且發量小的網路應用開發。
- 非阻塞I/O:是指應用程式執行 I/O 操作後,不會阻塞目前的線程,可以繼續執行其他的任務,隨後再透過輪詢或事件通知的形式,以取得呼叫的結果。特點是:相對來說複雜一些。適用於併發量較小、且不需要及時回應的網頁應用程式開發
同步與非同步 I/O
- 同步I/O:是指應用程式執行 I/O 操作後,要一直等到整個 I/O 完成後,才能獲得 I/O 回應。
- 非同步I/O:是指應用程式執行 I/O 操作後,不用等待完成和完成後的回應,而是繼續執行就可以。等到這次 I/O 完成後,回應會用事件通知的方式,告訴應用程式。
關於文件的一些常見小知識
#磁碟剩餘空間還很多,新檔案和目錄報空間不足。
- 排查想法:大機率是小檔案太多,inode用完了,可以用df -i。
du和df統計的硬碟使用情況不一致問題。
- du是統計被檔案系統記錄到的每個檔案的大小,然後進行累加得到的總大小,是透過檔案系統取得的。而df主要是從超級區塊(superblock)中讀入硬碟使用訊息,df取得到的是磁碟區塊被使用的情況。產生這種情況大機率是有檔案被刪除了,但是有別的進程正在使用它(佔有句柄),可以透過lsof | grep deleted查到。當行程停止或被kill時,這些空間將會被釋放。
我們查詢磁碟容量的時候,Used Avail的大小為啥總是小於總容量(SIze)。
- 為了預防緊急情況,linux ext檔案系統會預留部分硬碟空間,具體預留的數值可以透過tune2fs -l [dev_name] | grep “Reserved block count”查看到,(dev_name)是裝置名,這裡預留的空間會被df計算到已使用空間中,導致df和du統計不一致。如果需要調整預留空間大小, 我們可以使用tune2fs -m [size] [dev_name]來進行調整。
以上是想弄清楚Linux檔案系統的運作機制嗎?的詳細內容。更多資訊請關注PHP中文網其他相關文章!