簡介
首先要明白的是“什麼是檔案系統”,檔案系統是對一個存儲設備上的數據和元數據進行組織的機制。這種機制有利於用戶和作業系統的互動。在一篇oracle的技術文章中看到這樣一句話“儘管核心是 Linux 的核心,但檔案卻是用戶與作業系統互動所採用的主要工具。這對 Linux 來說尤其如此,這是因為在 UNIX 傳統中,它使用檔案 I/O 機制管理硬體設備和數據檔案”,這句話我是這樣理解的,在Linux沒有檔案系統的話,用戶和作業系統的互動也就斷開了,例如我們使用最多的互動shell,包括其它的一些用戶程式,都沒有辦法運行。在這裡可以看到檔案系統相對於Linux作業系統的重要性。下面是Linux檔案系統組件的體系結構。
用戶空間包含一些應用程式(例如,檔案系統的使用者)和 GNU C 庫(glibc),它們為檔案系統調用(打開、讀取、寫和關閉)提供用戶接口。系統調用接口的作用就像是交換器,它將系統調用從用戶空間傳送到核心空間中的適當端點。
VFS 是底層檔案系統的主要接口。這個組件導出一組接口,然後將它們抽象到各個檔案系統,各個檔案系統的行為可能差異很大。有兩個針對檔案系統對象的快取(inode 和dentry)。它們快取最近使用過的檔案系統對象。
每個檔案系統實現(比如 ext2、JFS 等等)導出一組通用接口,供 VFS 使用。緩衝區快取會快取檔案系統和相關塊設備之間的請求。例如,對底層設備驅動程式的讀寫請求會通過緩衝區快取來傳遞。這就允許在其中快取請求,減少訪問物理設備的次數,加快訪問速度。以最近使用(LRU)列表的形式管理緩衝區快取。注意,可以使用 sync 命令將緩衝區快取中的請求傳送到存儲媒體(迫使所有未寫的數據傳送到設備驅動程式,進而傳送到存儲設備)。
當我們在Windows下,提到檔案系統時,你的第一反應是想到的是什麼?是不是Windows下的一些Fat32、NTFS等的檔案系統的類型。而在Linux中,你可能會想到Ext2、Ext3,但你還必須要有一個根檔案系統的概念。根檔案系統首先是一種檔案系統,該檔案系統不僅具有普通檔案系統的存儲數據檔案的功能,但是相對於普通的檔案系統,它的特殊之處在於,它是核心啟動時所掛載(mount)的第一個檔案系統,核心代碼的映像檔案保存在根檔案系統中,系統引導啟動程式會在根檔案系統掛載之後從中把一些初始化腳本(如rcS,inittab)和服務載入到記憶體中去運行。我們要明白檔案系統和核心是完全獨立的兩個部分。在嵌入式中移植的核心下載到開發板上,是沒有辦法真正的啟動Linux作業系統的,會出現無法載入檔案系統的錯誤。
那么根檔案系統在系統啟動中到底是什麼時候掛載的呢?先將/dev/ram0掛載,而後執行/linuxrc.等其執行完後。切換根目錄,再掛載具體的根檔案系統.根檔案系統執行完之後,也就是到了Start_kernel()函式的最後,執行init的進程,也就第一個用戶進程。對系統進行各種初始化的操作。如果要弄明白這裡的過程的話,可要好好的看看Linux核心源碼了。下圖展示了VFS,核心,檔案系統的層次結構:
根檔案系統之所以在前面加一個”根“,說明它是載入其它檔案系統的”根“,既然是根的話,那么如果沒有這個根,其它的檔案系統也就沒有辦法進行載入的。它包含系統引導和使其他檔案系統得以掛載(mount)所必要的檔案。根檔案系統包括Linux啟動時所必須的目錄和關鍵性的檔案,例如Linux啟動時都需要有init目錄下的相關檔案,在 Linux掛載分區時Linux一定會找/etc/fstab這個掛載檔案等,根檔案系統中還包括了許多的應用程式bin目錄等,任何包括這些Linux 系統啟動所必須的檔案都可以成為根檔案系統。
Linux啟動時,第一個必須掛載的是根檔案系統;若系統不能從指定設備上掛載根檔案系統,則系統會出錯而退出啟動。成功之後可以自動或手動掛載其他的檔案系統。因此,一個系統中可以同時存在不同的檔案系統。
在 Linux 中將一個檔案系統與一個存儲設備關聯起來的過程稱為掛載(mount)。使用 mount 命令將一個檔案系統附著到當前檔案系統層次結構中(根)。在執行掛裝時,要提供檔案系統類型、檔案系統和一個掛裝點。根檔案系統被掛載到根目錄下“/”上後,在根目錄下就有根檔案系統的各個目錄,檔案:/bin /sbin /mnt等,再將其他分區掛接到/mnt目錄上,/mnt目錄下就有這個分區的各個目錄,檔案。
Linux根檔案系統中一般有如下圖的幾個目錄:
1./bin目錄
該目錄下的命令可以被root與一般賬號所使用,由於這些命令在掛接其它檔案系統之前就可以使用,所以/bin目錄必須和根檔案系統在同一個分區中。
/bin目錄下常用的命令有:cat、chgrp、chmod、cp、ls、sh、kill、mount、umount、mkdir、[、test等。其中“[”命令就是test命令,我們在利用Busybox製作根檔案系統時,在生成的bin目錄下,可以看到一些可執行的檔案,也就是可用的一些命令。
2./sbin 目錄
該目錄下存放系統命令,即只有系統管理員(俗稱最高許可權的root)能夠使用的命令,系統命令還可以存放在/usr/sbin,/usr/local/sbin目錄下,/sbin目錄中存放的是基本的系統命令,它們用於啟動系統和修復系統等,與/bin目錄相似,在掛接其他檔案系統之前就可以使用/sbin,所以/sbin目錄必須和根檔案系統在同一個分區中。
/sbin目錄下常用的命令有:shutdown、reboot、fdisk、fsck、init等,本地用戶自己安裝的系統命令放在/usr/local/sbin目錄下。
3、/dev目錄
該目錄下存放的是設備與設備接口的檔案,設備檔案是Linux中特有的檔案類型,在Linux系統下,以檔案的方式訪問各種設備,即通過讀寫某個設備檔案操作某個具體硬體。比如通過"dev/ttySAC0"檔案可以操作串口0,通過"/dev/mtdblock1"可以訪問MTD設備的第2個分區。比較重要的檔案有/dev/null, /dev/zero, /dev/tty, /dev/lp*等。
4./etc目錄
該目錄下存放著系統主要的配置檔案,例如人員的賬號密碼檔案、各種服務的其實檔案等。一般來說,此目錄的各檔案屬性是可以讓一般用戶查閱的,但是只有root有許可權修改。對於PC上的Linux系統,/etc目錄下的檔案和目錄非常多,這些目錄檔案是可選的,它們依賴於系統中所擁有的應用程式,依賴於這些程式是否需要配置檔案。在嵌入式系統中,這些內容可以大為精減。
5./lib目錄
該目錄下存放共享庫和可載入(驅動程式),共享庫用於啟動系統。運行根檔案系統中的可執行程式,比如:/bin /sbin 目錄下的程式。
6./home目錄
系統默認的用戶資料夾,它是可選的,對於每個普通用戶,在/home目錄下都有一個以用戶名命名的子目錄,裡面存放用戶相關的配置檔案。
7./root目錄
系統管理員(root)的主資料夾,即是根用戶的目錄,與此對應,普通用戶的目錄是/home下的某個子目錄。
8./usr目錄
/usr目錄的內容可以存在另一個分區中,在系統啟動後再掛接到根檔案系統中的/usr目錄下。裡面存放的是共享、唯讀的程式和數據,這表明/usr目錄下的內容可以在多個主機間共享,這些主要也符合FHS標準的。/usr中的檔案應該是唯讀的,其他主機相關的,可變的檔案應該保存在其他目錄下,比如/var。/usr目錄在嵌入式中可以精減。
9./var目錄
與/usr目錄相反,/var目錄中存放可變的數據,比如spool目錄(mail,news),log檔案,臨時檔案。
10./proc目錄
這是一個空目錄,常作為proc檔案系統的掛接點,proc檔案系統是個虛擬的檔案系統,它沒有實際的存儲設備,裡面的目錄,檔案都是由核心
臨時生成的,用來表示系統的運行狀態,也可以操作其中的檔案控制系統。
11./mnt目錄
用於臨時掛載某個檔案系統的掛接點,通常是空目錄,也可以在裡面創建一引起空的子目錄,比如/mnt/cdram /mnt/hda1 。用來臨時掛載光碟、移動存儲設備等。
12. /tmp目錄
用於存放臨時檔案,通常是空目錄,一些需要生成臨時檔案的程式用到的/tmp目錄下,所以/tmp目錄必須存在並可以訪問。
那我們利用Busybox製作根檔案系統就是創建這上面的這些目錄,和這些目錄下面的各種檔案。
對於嵌入式Linux系統的根檔案系統來說,一般可能沒有上面所列出的那么複雜,比如嵌入式系統通常都不是針對多用戶的,所以/home這個目錄在一般嵌入式Linux中可能就很少用到,而/boot這個目錄則取決於你所使用的BootLoader是否能夠重新獲得核心映象從你的根檔案系統在核心啟動之前。一般說來,只有/bin,/dev,/etc,/lib,/proc,/var,/usr這些需要的,而其他都是可選的。
根檔案系統一直以來都是所有類Unix作業系統的一個重要組成部分,也可以認為是嵌入式Linux系統區別於其他一些傳統嵌入式作業系統的重要特徵,它給 Linux帶來了許多強大和靈活的功能,同時也帶來了一些複雜性。我們需要清楚的了解根檔案系統的基本結構,以及細心的選擇所需要的系統庫、核心模組和應用程式等,並配置好各種初始化腳本檔案,以及選擇合適的檔案系統類型並把它放到實際的存儲設備的合適位置,下面是幾中比較常用的檔案系統。
檔案系統
(1)jffs2
JFFS嵌入式系統檔案系統最早是由瑞典 Axis Communications公司基於Linux2.0的核心為嵌入式系統開發的檔案系統。JFFS2是RedHat公司
基於JFFS開發的快閃記憶體檔案系統,最初是針對RedHat公司的嵌入式產品eCos開發的嵌入式檔案系統,所以JFFS2也可以用在Linux, uCLinux中。
Jffs2: 日誌快閃記憶體嵌入式系統檔案系統版本2 (Journalling Flash FileSystem v2)
主要用於NOR型快閃記憶體,基於MTD驅動層,特點是:可讀寫的、支持數據壓縮的、基於哈希表的日誌型檔案系統,並提供了崩潰/掉電安全保護,提供“寫平衡”支持等。缺點主要是當檔案系統已滿或接近滿時,因為垃圾收集的關係而使jffs2的運行速度大大放慢。目前jffs3正在開發中。關於jffs系列檔案系統的使用詳細文檔,可參考MTD補丁包中mtd-jffs-HOWTO.txt。
jffsx不適合用於NAND快閃記憶體主要是因為NAND快閃記憶體的容量一般較大,這樣導致jffs為維護日誌節點所占用的記憶體空間迅速增大,另外,jffsx檔案系統在掛載時需要掃描整個FLASH的內容,以找出所有的日誌節點,建立檔案結構,對於大容量的NAND快閃記憶體會耗費大量時間。
(2)yaffs:Yet Another Flash File System
yaffs/yaffs2是專為嵌入式系統使用 NAND型快閃記憶體而設計的一種日誌型檔案系統。與jffs2相比,它減少了一些功能(例如不支持數據壓縮),所以速度更快,掛載時間很短,對記憶體的占用較小。另外,它還是跨平台的檔案系統,除了Linux和eCos,還支持WinCE, pSOS和ThreadX等。
yaffs/yaffs2自帶NAND晶片的驅動,並且為嵌入式系統提供了直接訪問檔案系統的API,用戶可以不使用Linux中的MTD與VFS,直接對檔案系統操作。當然,yaffs也可與MTD驅動程式配合使用。
yaffs與 yaffs2的主要區別在於,前者僅支持小頁(512 Bytes) NAND快閃記憶體,後者則可支持大頁(2KB) NAND快閃記憶體。同時,yaffs2在記憶體空間占用、垃圾回收速度、讀/寫速度等方面均有大幅提升。
(3) Cramfs:Compressed ROM File System
Cramfs是Linux的創始人 Linus Torvalds參與開發的一種唯讀的壓縮檔案系統。它也基於MTD驅動程式。在cramfs檔案系統中,每一頁(4KB)被單獨壓縮,可以隨機頁訪問,其壓縮比高達2:1,為嵌入式系統節省大量的Flash存儲空間,使系統可通過更低容量的FLASH存儲相同的檔案,從而降低系統成本。
Cramfs檔案系統以壓縮方式存儲,在運行時解壓縮,所以不支持應用程式以XIP方式運行,所有的應用程式要求被拷到RAM里去運行,但這
並不代表比 Ramfs需求的RAM空間要大一點,因為Cramfs是採用分頁壓縮的方式存放檔案,在讀取檔案時,不會一下子就耗用過多的記憶體空間,
只針對目前實際讀取的部分分配記憶體,尚沒有讀取的部分不分配記憶體空間,當我們讀取的檔案不在記憶體時,Cramfs檔案系統自動計算壓縮後的資料所存的位置,再即時解壓縮到 RAM中。另外,它的速度快,效率高,其唯讀的特點有利於保護檔案系統免受破壞,提高了系統的可靠性。
由於以上特性,Cramfs在嵌入式系統中套用廣泛。但是它的唯讀屬性同時又是它的一大缺陷,使得用戶無法對其內容對進擴充。Cramfs映像通常是放在Flash中,但是也能放在別的檔案系統里,使用 loopback 設備可以把它安裝別的檔案系統里。
(4)網路檔案系統NFS (Network File System)
NFS是由Sun開發並發展起來的一項在不同機器、不同作業系統之間通過網路已分享檔案的技術。在嵌入式Linux系統的開發調試階段,可以利用該技術在主機上建立基於NFS 的根檔案系統,掛載到嵌入式設備,可以很方便地修改根檔案系統的內容。以上討論的都是基於存儲設備的檔案系統(memory-based file system),它們都可用作Linux的根檔案系統。實際上,Linux還支持邏輯的或偽檔案系統(logical or pseudo file system),例如procfs(proc檔案系統),用於獲取系統信息,以及devfs(設備檔案系統)和sysfs,用於維護設備檔案。