Linux 文件系統概覽
本文旨在高屋建瓴地來討論 Linux 文件系統概念,而不是對某種特定的文件系統,比如 EXT4 是如何工作的進行具體的描述。另外,本文也不是一個文件系統命令的教程。
每台通用計算機都需要將各種數據存儲在硬碟驅動器(HDD)或其他類似設備上,比如 USB 存儲器。這樣做有兩個原因。首先,當計算機關閉以後,內存(RAM)會失去存於它裡面的內容。儘管存在非易失類型的 RAM,在計算機斷電以後還能把數據存儲下來(比如採用 USB 快閃記憶體和固態硬碟的快閃記憶體),但是,快閃記憶體和標準的、易失性的 RAM,比如 DDR3 以及其他相似類型的 RAM 相比,要貴很多。
數據需要存儲在硬碟驅動上的另一個原因是,即使是標準的 RAM 也要比普通硬碟貴得多。儘管 RAM 和硬碟的價格都在迅速下降,但是 RAM 的價格依舊在以位元組為單位來計算。讓我們進行一個以位元組為單位的快速計算:基於 16 GB 大的 RAM 的價格和 2 TB 大的硬碟驅動的價格。計算顯示 RAM 的價格大約比硬碟驅動貴 71 倍。今天,一個典型的 RAM 的價格大約是 0.000000004373750 美元/每位元組。
直觀的展示一下在很久以前 RAM 的價格,在計算機發展的非常早的時期,其中一種類型的 RAM 是基於在 CRT 屏幕上的點。這種 RAM 非常昂貴,大約 1 美元/每位元組。
定義
你可能聽過其他人以各種不同和令人迷惑的方式談論過文件系統。文件系統這個單詞本身有多重含義,你需要從一個討論或文件的上下文中理解它的正確含義。
我將根據我所觀察到的在不同情況下使用「文件系統」這個詞來定義它的不同含義。注意,儘管我試圖遵循標準的「官方」含義,但是我打算基於它的不同用法來定義這個術語(如下)。這就是說我將在本文的後續章節中進行更詳細的探討。
- 始於頂層 root(
/
)目錄的整個 Linux 目錄結構。 - 特定類型的數據存儲格式,比如 EXT3、EXT4、BTRFS 以及 XFS 等等。Linux 支持近百種類型的文件系統,包括一些非常老的以及一些最新的。每一種文件系統類型都使用它自己獨特的元數據結構來定義數據是如何存儲和訪問的。
- 用特定類型的文件系統格式化後的分區或邏輯卷,可以掛載到 Linux 文件系統的指定掛載點上。
文件系統的基本功能
磁碟存儲是文件系統必須的功能,它與之伴生的有一些有趣而且不可或缺的細節。很明顯,文件系統是用來為非易失數據的存儲提供空間,這是它的基本功能。然而,它還有許多從需求出發的重要功能。
所有文件系統都需要提供一個名字空間,這是一種命名和組織方法。它定義了文件應該如何命名、文件名的最大長度,以及所有可用字符集中可用於文件名中字符集子集。它也定義了一個磁碟上數據的邏輯結構,比如使用目錄來組織文件而不是把所有文件聚集成一個單一的、巨大的文件混合體。
定義名字空間以後,元數據結構是為該名字空間提供邏輯基礎所必須的。這包括所需數據結構要能夠支持分層目錄結構,同時能夠通過結構來確定硬碟空間中的塊是已用的或可用的,支持修改文件或目錄的名字,提供關於文件大小、創建時間、最後訪問或修改時間等信息,以及位置或數據所屬的文件在磁碟空間中的位置。其他的元數據用來存儲關於磁碟細分的高級信息,比如邏輯卷和分區。這種更高層次的元數據以及它所代表的結構包含描述文件系統存儲在驅動器或分區中的信息,但與文件系統元數據無關,與之獨立。
文件系統也需要一個應用程序介面(API),從而提供了對文件系統對象,比如文件和目錄進行操作的系統功能調用的訪問。API 也提供了諸如創建、移動和刪除文件的功能。它也提供了演算法來確定某些信息,比如文件存於文件系統中的位置。這樣的演算法可以用來解釋諸如磁碟速度和最小化磁碟碎片等術語。
現代文件系統還提供一個安全模型,這是一個定義文件和目錄的訪問許可權的方案。Linux 文件系統安全模型確保用戶只能訪問自己的文件,而不能訪問其他用戶的文件或操作系統本身。
最後一塊組成部分是實現這些所有功能所需要的軟體。Linux 使用兩層軟體實現的方式來提高系統和程序員的效率。
圖片 1:Linux 兩層文件系統軟體實現。
這兩層中的第一層是 Linux 虛擬文件系統。虛擬文件系統提供了內核和開發者訪問所有類型文件系統的的單一命令集。虛擬文件系統軟體通過調用特殊設備驅動來和不同類型的文件系統進行交互。特定文件系統的設備驅動是第二層實現。設備驅動程序將文件系統命令的標準集解釋為在分區或邏輯卷上的特定類型文件系統命令。
目錄結構
作為一個通常來說非常有條理的處女座,我喜歡將東西存儲在更小的、有組織的小容器中,而不是存於同一個大容器中。目錄的使用使我能夠存儲文件並在我想要查看這些文件的時候也能夠找到它們。目錄也被稱為文件夾,之所以被稱為文件夾,是因為其中的文件被類比存放於物理桌面上。
在 Linux 和其他許多操作系統中,目錄可以被組織成樹狀的分層結構。在 Linux 文件系統層次標準中定義了 Linux 的目錄結構(LCTT 譯註:可參閱這篇)。當通過目錄引用來訪問目錄時,更深層目錄名字是通過正斜杠(/)來連接,從而形成一個序列,比如 /var/log
和 /var/spool/mail
。這些被稱為路徑。
下表提供了標準的、眾所周知的、預定義的頂層 Linux 目錄及其用途的簡要清單。
目錄 | 描述 |
---|---|
/ (root 文件系統) | root 文件系統是文件系統的頂級目錄。它必須包含在掛載其它文件系統前需要用來啟動 Linux 系統的全部文件。它必須包含需要用來啟動剩餘文件系統的全部可執行文件和庫。文件系統啟動以後,所有其他文件系統作為 root 文件系統的子目錄掛載到標準的、預定義好的掛載點上。 |
/bin | /bin 目錄包含用戶的可執行文件。 |
/boot | 包含啟動 Linux 系統所需要的靜態引導程序和內核可執行文件以及配置文件。 |
/dev | 該目錄包含每一個連接到系統的硬體設備的設備文件。這些文件不是設備驅動,而是代表計算機上的每一個計算機能夠訪問的設備。 |
/etc | 包含主機計算機的本地系統配置文件。 |
/home | 主目錄存儲用戶文件,每一個用戶都有一個位於 /home 目錄中的子目錄(作為其主目錄)。 |
/lib | 包含啟動系統所需要的共享庫文件。 |
/media | 一個掛載外部可移動設備的地方,比如主機可能連接了一個 USB 驅動器。 |
/mnt | 一個普通文件系統的臨時掛載點(如不可移動的介質),當管理員對一個文件系統進行修復或在其上工作時可以使用。 |
/opt | 可選文件,比如供應商提供的應用程序應該安裝在這兒。 |
/root | 這不是 root(/ )文件系統。它是 root 用戶的主目錄。 |
/sbin | 系統二進位文件。這些是用於系統管理的可執行文件。 |
/tmp | 臨時目錄。被操作系統和許多程序用來存儲臨時文件。用戶也可能臨時在這兒存儲文件。注意,存儲在這兒的文件可能在任何時候在沒有通知的情況下被刪除。 |
/usr | 該目錄裡面包含可共享的、只讀的文件,包括可執行二進位文件和庫、man 文件以及其他類型的文檔。 |
/var | 可變數據文件存儲在這兒。這些文件包括日誌文件、MySQL 和其他資料庫的文件、Web 伺服器的數據文件、郵件以及更多。 |
表 1:Linux 文件系統層次結構的頂層
這些目錄以及它們的子目錄如表 1 所示,在所有子目錄中,粗體的目錄組成了 root 文件系統的必需部分。也就是說,它們不能創建為一個分離的文件系統並且在開機時進行掛載。這是因為它們(特別是它們包含的內容)必須在系統啟動的時候出現,從而系統才能正確啟動。
/media
目錄和 /mnt
目錄是 root 文件系統的一部分,但是它們從來不包含任何數據,因為它們只是一個臨時掛載點。
表 1 中剩下的非粗體的目錄不需要在系統啟動過程中出現,但會在之後掛載到 root 文件系統上,在開機階段,它們為主機進行準備,從而執行有用的工作。
請參考官方 Linux 文件系統層次標準(FHS)網頁來了解這些每一個目錄以及它們的子目錄的更多細節。維基百科上也有關於 FHS 的一個很好的介紹。應該儘可能的遵循這些標準,從而確保操作和功能的一致性。無論在主機上使用什麼類型的文件系統,該層次目錄結構都是相同的。
Linux 統一目錄結構
在一些非 Linux 操作系統的個人電腦上,如果有多個物理硬碟驅動器或多個分區,每一個硬碟或分區都會分配一個驅動器號。知道文件或程序位於哪一個硬碟驅動器上是很有必要的,比如 C:
或 D:
。然後,你可以在命令中使用驅動器號,以 D:
為例,為了進入 D:
驅動器,你可以使用 cd
命令來更改工作目錄為正確的目錄,從而定位需要的文件。每一個硬碟驅動器都有自己單獨的、完整的目錄樹。
Linux 文件系統將所有物理硬碟驅動器和分區統一為一個目錄結構。它們均從頂層 root 目錄(/
)開始。所有其它目錄以及它們的子目錄均位於單一的 Linux 根目錄下。這意味著只有一棵目錄樹來搜索文件和程序。
因為只有一個文件系統,所以 /home
、/tmp
、/var
、/opt
或 /usr
能夠創建在和 root(/
)文件系統不同的物理硬碟驅動器、分區或邏輯分區上,然後掛載到一個掛載點(目錄)上,從而作為 root 文件系統樹的一部分。甚至可移動驅動器,比如 USB 驅動器或一個外接的 USB 或 ESATA 硬碟驅動器均可以掛載到 root 文件系統上,成為目錄樹不可或缺的部分。
當從 Linux 發行版的一個版本升級到另一個版本或從一個發行版更改到另一個發行版的時候,就會很清楚地看到這樣創建到不同分區的好處。通常情況下,除了任何像 Fedora 中的 dnf-upgrade
之類的升級工具,會明智地在升級過程中偶爾重新格式化包含操作系統的硬碟驅動來刪除那些長期積累的垃圾。如果 /home
目錄是 root 文件系統的一部分(位於同一個硬碟驅動器),那麼它也會被格式化,然後需要通過之前的備份恢復。如果 /home 目錄作為一個分離的文件系統,那麼安裝程序將會識別到,並跳過它的格式化。對於存儲資料庫、郵箱、網頁和其它可變的用戶以及系統數據的 /var
目錄也是這樣的。
將 Linux 系統目錄樹的某些部分作為一個分離的文件系統還有一些其他原因。比如,在很久以前,我還不知道將所有需要的 Linux 目錄均作為 root(/
)文件系統的一部分可能存在的問題,於是,一些非常大的文件填滿了 /home
目錄。因為 /home
目錄和 /tmp
目錄均不是分離的文件系統,而是 root 文件系統的簡單子目錄,整個 root 文件系統就被填滿了。於是就不再有剩餘空間可以讓操作系統用來存儲臨時文件或擴展已存在數據文件。首先,應用程序開始抱怨沒有空間來保存文件,然後,操作系統也開始異常行動。啟動到單用戶模式,並清除了 /home
目錄中的多餘文件之後,終於又能夠重新工作了。然後,我使用非常標準的多重文件系統設置來重新安裝 Linux 系統,從而避免了系統崩潰的再次發生。
我曾經遇到一個情況,Linux 主機還在運行,但是卻不允許用戶通過 GUI 桌面登錄。我可以通過使用虛擬控制台之一,通過命令行界面(CLI)本地登錄,然後遠程使用 SSH 。問題的原因是因為 /tmp
文件系統滿了,因此 GUI 桌面登錄時所需要的一些臨時文件不能被創建。因為命令行界面登錄不需要在 /tmp
目錄中創建文件,所以無可用空間並不會阻止我使用命令行界面來登錄。在這種情況下,/tmp
目錄是一個分離的文件系統,在 /tmp
所位於的邏輯卷上還有大量的可用空間。我簡單地擴展了 /tmp 邏輯卷的容量到能夠容納主機所需要的臨時文件,於是問題便解決了。注意,這個解決方法不需要重啟,當 /tmp
文件系統擴大以後,用戶就可以登錄到桌面了。
當我在一家很大的科技公司當實驗室管理員的時候,遇到過另外一個故障。開發者將一個應用程序安裝到了一個錯誤的位置(/var
)。結果該應用程序崩潰了,因為 /var
文件系統滿了,由於缺乏空間,存儲於 /var/log
中的日誌文件無法附加新的日誌消息。然而,系統仍然在運行,因為 root 文件系統和 /tmp
文件系統還沒有被填滿。刪除了該應用程序並重新安裝在 /opt
文件系統後,問題便解決了。
文件系統類型
Linux 系統支持大約 100 種分區類型的讀取,但是只能對很少的一些進行創建和寫操作。但是,可以掛載不同類型的文件系統在同一個 root 文件系統上,並且是很常見的。在這樣的背景下,我們所說的文件系統一詞是指在硬碟驅動器或邏輯卷上的一個分區中存儲和管理用戶數據所需要的結構和元數據。能夠被 Linux 系統的 fdisk
命令識別的文件系統類型的完整列表在此,你可以感受一下 Linux 系統對許多類型的系統的高度兼容性。
Linux 支持讀取這麼多類型的分區系統的主要目的是為了提高兼容性,從而至少能夠與一些其他計算機系統的文件系統進行交互。下面列出了在 Fedora 中創建一個新的文件系統時的所有可選類型:
- btrfs
- cramfs
- ext2
- ext3
- ext4
- fat
- gfs2
- hfsplus
- minix
- msdos
- ntfs
- reiserfs
- vfat
- xfs
其他發行版支持創建的文件系統類型不同。比如,CentOS 6 只支持創建上表中標為黑體的文件系統類型。
掛載
在 Linux 系統上「 掛載 」文件系統的術語是指在計算機發展的早期,磁帶或可移動的磁碟組需要需要物理地掛載到一個合適的驅動器設備上。當通過物理的方式放置到驅動器上以後,操作系統會邏輯地掛載位於磁碟上的文件系統,從而操作系統、應用程序和用戶才能夠訪問文件系統中的內容。
一個掛載點簡單的來說就是一個目錄,就像任何其它目錄一樣,是作為 root 文件系統的一部分創建的。所以,比如,home 文件系統是掛載在目錄 /home
下。文件系統可以被掛載到其他非 root 文件系統的掛載點上,但是這並不常見。
在 Linux 系統啟動階段的最初階段,root 文件系統就會被掛載到 root 目錄下(/
)。其它文件系統在之後通過 SystemV 下的 rc
或更新一些的 Linux 發行版中的 systemd
等 Linux 啟動程序掛載。在啟動進程中文件系統的掛載是由 /etc/fstab
配置文件管理的。一個簡單的記憶方法是,fstab 代表「 文件系統表 」,它包含了需要掛載的文件系統的列表,這些文件系統均指定了掛載點,以及針對特定文件系統可能需要的選項。
使用 mount
命令可以把文件系統掛載到一個已有的目錄/掛載點上。通常情況下,任何作為掛載點的目錄都應該是空的且不包含任何其他文件。Linux 系統不會阻止用戶掛載一個已被掛載了文件系統的目錄或將文件系統掛載到一個包含文件的目錄上。如果你將文件系統掛載到一個已有的目錄或文件系統上,那麼其原始內容將會被隱藏,只有新掛載的文件系統的內容是可見的。
結論
我希望通過這篇文章,闡明了圍繞文件系統這個術語的一些可能的模糊之處。我花費了很長的時間,以及在一個良師的幫助下才真正理解和欣賞到 Linux 文件系統的複雜性、優雅性和功能以及它的全部含義。
如果你有任何問題,請寫到下面的評論中,我會儘力來回答它們。
下個月
Linux 的另一個重要概念是:萬物皆為文件。這個概念對用戶和系統管理員來說有一些有趣和重要的實際應用。當我說完這個理由之後,你可能會想閱讀我的文章:萬物皆為文件,這篇文章會在我下個月計劃寫的關於 /dev
目錄的文章之前寫完。(LCTT 譯註,也可參閱這篇)
(題圖 : wallup.net)
作者簡介:
David Both 居住在美國北卡羅納州的首府羅利,是一個 Linux 開源貢獻者。他已經從事 IT 行業 40 余年,在 IBM 教授 OS/2 20 余年。1981 年,他在 IBM 開發了第一個關於最初的 IBM 個人電腦的培訓課程。他也曾在 Red Hat 教授 RHCE 課程,也曾供職於 MCI worldcom,Cico 以及北卡羅納州等。他已經為 Linux 開源社區工作近 20 年。
via: https://opensource.com/life/16/10/introduction-linux-filesystems
作者:David Both 譯者:ucasFL 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive