文件系統(tǒng)可以說是嵌入式中的一大塊,也是繞不過的一部分。之前我對文件系統(tǒng)認知一直停留在在U盤格式的理解上,直到接觸了嵌入式Linux才發(fā)現(xiàn)這里面大有文章,以Linux啟動掛載根文件系統(tǒng)為例,這個文件系統(tǒng)可以是真正的存儲設備上的文件系統(tǒng),也可以是網(wǎng)絡文件系統(tǒng),甚至可以開辟一段內(nèi)存,虛擬出來一個文件系統(tǒng),這些在一開始接觸嵌入式Linux開發(fā)的時候就算講到了講的也不會很深,我之前跟著某點教程走了一遍之后腦子里樹立起來了這個文件系統(tǒng)的概念,但是感覺還是模模糊糊,后來陸陸續(xù)續(xù)看了一些文章還有視頻,才慢慢有了較為清晰的認識。
了解了這些文件系統(tǒng)相關的知識,對理解Linux使用也有幫助,因為根目錄下的許多主要目錄都是基于文件系統(tǒng)虛擬出來的。
在這里強烈推薦大家入門接觸根文件系統(tǒng)以后,看一下麥子學院的有一個專門講文件系統(tǒng)的教程,講的非常詳細(墻裂推薦),教程鏈接地址我放在文章最后,大家需要自取。
下面是我自己的個人筆記相關,大家也可以自己去看一遍完整的教程,如有錯誤,歡迎指正。
嵌入式常用文件系統(tǒng)
這是整個文件系統(tǒng)的勾勒圖,下面將以這個圖展開進行介紹
查看本機所有文件系統(tǒng)
使用df -ahT
命令查看當前系統(tǒng)的所有文件系統(tǒng)
-h
顯示大小
-T
顯示文件系統(tǒng)類型
-a
打印所有文件系統(tǒng)
文件系統(tǒng)總體介紹
一、內(nèi)核生成的文件系統(tǒng)
sysfs
與proc
文件系統(tǒng)是內(nèi)核自動生成的文件系統(tǒng) 。
分為兩類:
一類文件系統(tǒng)有大小,稱為基于存儲設備的文件系統(tǒng)
。
一類文件系統(tǒng)根本無法查看大小,稱為基于邏輯的虛擬文件系統(tǒng)
。
二、存儲設備文件系統(tǒng)
基于存儲設備的文件系統(tǒng)
可以分為內(nèi)存文件系統(tǒng)
和flash文件系統(tǒng)
和擴展SD卡文件系統(tǒng)
和網(wǎng)絡文件系統(tǒng)
。
三、內(nèi)存文件系統(tǒng)
內(nèi)存文件系統(tǒng)
包括tmpfs
和ramdisk
。
tmpfs
文件系統(tǒng)是一種臨時的文件系統(tǒng),是由linux內(nèi)核來支持的,只需要在內(nèi)存中指定一個區(qū)域,指定最大的大小,就可以直接使用,不需要對內(nèi)存進行格式化。
ramdisk
是將一部分固定大小的內(nèi)存( RAM )空間模擬出硬盤分區(qū),斷電后會丟失。
四、flash文件系統(tǒng)
flash
文件系統(tǒng)包括cramfs
和squashfs
和jffs/jffs2
和yaffs/yaffs2
和ubifs
。
cramfs
是只讀壓縮的文件系統(tǒng),可以將文件系統(tǒng)進行壓縮,提高存儲效率。
squashfs
是只讀壓縮的文件系統(tǒng),相比于cramfs
可以支持更大的單個文件大小。
jffs/jffs2
是可以讀寫,壓縮的日志閃存文件系統(tǒng),主要是應用于nor flash
。
yaffs/yaffs2
是另一種日志閃存文件系統(tǒng),主要是為nand
型flash
設計的文件系統(tǒng),為了應對flash
容量的快速增長。
ubifs
是作為jffs2
的后繼文件系統(tǒng),滿足大容量的需求。
五、擴展文件系統(tǒng)
擴展SD卡文件系統(tǒng)
包括FAT32
和ext2/ext3
。
FAT32
是微軟專為windows開發(fā)的文件系統(tǒng),在windows上有很好的兼容性。
ext2/ext3
是Linux上的日志文件系統(tǒng),可靠性好,但在windows上支持不太好。
六、網(wǎng)絡文件系統(tǒng)
網(wǎng)絡文件系統(tǒng)
包括NFS
和Samba
。
NFS
是開發(fā)板與宿主機進行掛載的文件系統(tǒng)。
Samba
是windows與Linux之間的共享機制。
七、虛擬文件系統(tǒng)
虛擬文件系統(tǒng)無法查看大小,稱為基于邏輯的虛擬文件系統(tǒng)
。
基于邏輯的虛擬文件系統(tǒng)
包括進程文件系統(tǒng)
和設備文件系統(tǒng)
。
進程文件系統(tǒng)
在Linux上常用的是procfs
文件系統(tǒng),Linux啟動以后自動掛載在/proc
目錄下。
設備文件系統(tǒng)
在Linux上常用的是sysfs
文件系統(tǒng)與devfs
文件系統(tǒng),sysfs
文件系統(tǒng)在Linux啟動以后,自動掛載在sys
目錄下。
但devfs
文件系統(tǒng)在Linux內(nèi)核2.6以前使用,現(xiàn)在基本被廢棄。
八、存儲設備
存儲設備可以分為內(nèi)存
和外存
和網(wǎng)絡
,外存還可以分為內(nèi)置
和擴展
。
內(nèi)存
對應三、內(nèi)存文件系統(tǒng)
。
外存
對應四、flash文件系統(tǒng)
。
網(wǎng)絡
對應六、網(wǎng)絡文件系統(tǒng)
。
內(nèi)置
包括四、flash文件系統(tǒng)
與三、內(nèi)存文件系統(tǒng)
。
擴展
對應五、擴展文件系統(tǒng)
。
九、配置選項
要在嵌入式系統(tǒng)上使用這些文件系統(tǒng),內(nèi)核必須支持這些文件系統(tǒng) 。
所以linux內(nèi)核裁剪的時候進行配置。
Linux內(nèi)核虛擬文件系統(tǒng)
目的是為了使用與文件接口統(tǒng)一的操作來完成系統(tǒng)信息管理
。
包括procfs 、 devfs 、 sysfs
。
內(nèi)核中首先需要配置支持這三種文件系統(tǒng)
procfs
是Linux內(nèi)核信息的抽象文件接口,大量的內(nèi)核中的信息以及可調(diào)參數(shù)都被作為常規(guī)文件映射到了一個目錄樹中/proc
。
這樣我們就可以簡單直接的通過echo
和cat
這樣的文件操作命令對系統(tǒng)信息進行查取和調(diào)整了。
大量的系統(tǒng)工具也通過procfs
來獲取內(nèi)核參數(shù),例如ps
、lspci
等。
一、procfs文件系統(tǒng)
首先對procfs進行掛載
# -t 是指定文件系統(tǒng)類型 ,第二個參數(shù)是掛載設備,因為是內(nèi)核設備,所以寫none,第三個參數(shù)是掛載目錄
mount -t proc none /proc
# 或者在 /etc/fstab條目下添加
none /proc proc defaults 0 0
在fstab下添加會在開機以后自動掛載
一旦proc卸載掉,那么df
命令就無法使用了。
因為df
命令實際是去查看/proc/mounts
文件來查看信息。
很多命令例如ps
都是通過proc
目錄來查看系統(tǒng)信息。
再查看一下proc
目錄下的文件:帶數(shù)字的表示是進程信息 。
其他的都是系統(tǒng)信息
cmdline
文件表示內(nèi)核啟動參數(shù)。
cpuinfo
文件表示cpu信息。
meminfo
文件表示內(nèi)存信息。
sys
目錄表示系統(tǒng)運行相關的信息,包括內(nèi)核等,但斷電后重新上電會再次使用默認設置。
二、tmpfs文件系統(tǒng)
是一種虛擬內(nèi)存文件系統(tǒng),使用內(nèi)存作為存儲分區(qū)進行文件的臨時性存取,掉電會丟失,創(chuàng)建時不需要使用mkfs
進行格式化
使用如下命令進行掛載。
# -o 指定大小
mount -t tmpfs none -o size=10M /tmp
所以一般tmp
目錄都是臨時創(chuàng)建的虛擬文件系統(tǒng)。
在這個文件夾下創(chuàng)建的文件斷電后會丟失。
所以通常使用這個目錄保存應用程序運行時的信息,不用擔心丟失。
作用是通過內(nèi)存的讀取速度提高程序效率,延長flash壽命
。
三、devfs文件系統(tǒng)
Linux2.6內(nèi)核以前設備文件的抽象機制:提供了一種類似于文件的方法來管理位于/dev
目錄下的所有設備。
特殊設備文件/dev/console
以及/dev/tty
。
/dev
目錄下的zero
以及null
是黑洞文件,相當于輸入給黑洞文件的信息全部都會消失。
devfs
文件系統(tǒng)后來集成到了sysfs
文件系統(tǒng)。
devfs缺點:設備映射不同,沒有主/次設備號,不能支持太多設備。
四、sysfs文件系統(tǒng)
Linux內(nèi)核2.6以后引入sysfs
文件系統(tǒng):掛載于/sys
目錄下,把實際連接到系統(tǒng)上的設備和總線組織成一個分級的文件。
用戶空間的程序也同樣可以使用這些信息實現(xiàn)和內(nèi)核的交互,該文件系統(tǒng)是當前系統(tǒng)上實際設備樹的一個直觀反映。
這些信息比/dev
目錄下的信息更為詳細與豐富,準確。
每個設備在sysfs
中都有唯一對應的目錄。
使用如下命令創(chuàng)建掛載點
## -t 是指定文件系統(tǒng)類型 ,第二個參數(shù)是掛載設備,因為是內(nèi)核設備,所以寫none,第三個參數(shù)是掛載目錄
mount -t sysfs none /sys
# 或者在 /etc/fstab條目下添加
none /sys sysfs defaults 0 0
# 在fstab下添加會在開機以后自動掛載
udev
工具是管理熱插拔的工具,利用了sysfs
提供的信息來實現(xiàn)所有devfs
的功能,通過檢測設備的插入與拔出,動態(tài)的在/dev
目錄下創(chuàng)建與刪除設備文件。
總結:一切皆文件的抽象思想,使得Linux系統(tǒng)的管理變得簡單統(tǒng)一。
嵌入式網(wǎng)絡文件系統(tǒng)
一、Network FileSystem
通過NFS掛載遠程主機目錄,訪問該目錄就像訪問本地目錄一樣。
使用NFS服務能夠方便的使各Linux系統(tǒng)之間實現(xiàn)共享。
Samba:在Linux與windows系統(tǒng)之間共享?;贑/S模式,客戶端-服務器模式。使用RPC(Remote Procedure Call,遠程過程調(diào)用)。
RPC定義了一種與系統(tǒng)無關的方法來實現(xiàn)進程間通信。
二、NFS服務安裝
# 安裝nfs
sudo apt-get install nfs-kernel-server
# 查看使用幫助
sudo server nfs-kernel-server
# 查看nfs服務狀態(tài)
sudo server nfs-kernel-server status
# 啟動nfs服務
sudo server nfs-kernel-server start
# 關閉nfs服務
sudo server nfs-kernel-server stop
# 重啟nfs服務
sudo server nfs-kernel-server restart
# 重新加載配置文件
sudo server nfs-kernel-server reload
# 強制重新加載配置文件
sudo server nfs-kernel-server force-reload
三、NFS設置
/etc/exports
控制著nfs服務器導出的訪問目錄列表 。
示例/home/yuzhou/linux/nfs *(rw,sync,no_root_squash)
規(guī)則
/home/yuzhou/linux/nfs 表示要共享的目錄
*表示主機名,或者域名或者ip地址,* 表示允許所有主機訪問
(rw,sync,no_root_squash)表示共享參數(shù)
rw,表示允許讀寫
sync,表示實時同步
no_suntree_check,表示不檢測是否為共享目錄的子目錄
no_root_squash,表示root用戶擁有所有權限
showmount -a
顯示所有客戶端的ip地址
showmount -e
顯示所有導出的目錄列表
exportfs -r
重新加載導出列表
三、開發(fā)板使用NFS
確保宿主機關閉防火墻,如果可以連接,也可以不關。
nfs內(nèi)核支持 , Network FileSystem --> [] NFS Client。
查看開發(fā)板kernel是否支持NFS,使用cat /proc/filesystem
命令,檢查是否有NFS一行,如下圖所示。
使用如下命令手動掛載nfs目錄。
# -t指定文件系統(tǒng)類型 目標設備 掛載點
mount -t nfs 192.168.1.10:/home/nfs /tmp
initramfs文件系統(tǒng)
內(nèi)核啟動的時候需要掛載根文件系統(tǒng),所以要在內(nèi)核鏡像中對存儲設備進行初始化,但這樣會導致內(nèi)核鏡像過大。所以可以使用ramfs文件系統(tǒng)
。
一、rootfs、ramfs、ramdisk與tmpfs區(qū)別
-
rootfs
與根文件系統(tǒng)的英文rootfs
不同,它是指內(nèi)核啟動的初始根文件系統(tǒng),內(nèi)核自身虛擬了一個文件系統(tǒng),如果這個空間內(nèi)沒有文件系統(tǒng),就回去查找其他文件系統(tǒng)。 -
ramfs
是基于內(nèi)存的文件系統(tǒng),沒有內(nèi)存大小的限制,會動態(tài)增加容量,直至耗盡系統(tǒng)內(nèi)存,使用的是基于內(nèi)存的緩存,所以io效率高。 -
ramdisk
是基于ram
的塊設備
,占據(jù)一塊固定的內(nèi)存,使用mke2fs
格式化工具創(chuàng)建文件系統(tǒng),還需要一個文件系統(tǒng)驅動來讀寫其中的文件??臻g固定導致容量有限,想要寫入更多內(nèi)容需要重新格式化。由于Linux塊設備緩沖的特點,所以ramdisk
上的數(shù)據(jù)會被拷貝到內(nèi)存上進行備份,造成內(nèi)存浪費。 -
ramfs
的缺點是可能不同增長直至耗盡內(nèi)存,所以只有root
用戶或者被收授權的用戶可以允許使用ramfs
,但是tmpfs
增加了容量的限制,允許用戶把數(shù)據(jù)寫入交換分區(qū),允許普通用戶使用。
二、initrd與initramfs
-
initrd
是intramfs
之前的設計 。 -
作用都是為了在掛載真正的根文件系統(tǒng)之前將設備驅動,工具以及一些初始化流程先加載到內(nèi)存中運行。 -
initrd
基于ramdisk
技術,initrd
的初始化程序是/linuxrc
文件,負責 最終完成真正根文件系統(tǒng)的掛載。我們的Ubuntu上都會有一個boot
目錄,內(nèi)核從boot
分區(qū)找到initrd
鏡像,然后由initrd
鏡像完成真正跟文件系統(tǒng)的掛載。在PC上initrd
用的比較少,initramfs
在嵌入式用的多。 -
initramfs
的實現(xiàn)設計比initrd
更簡單,靈活一點。是基于ramfs
文件系統(tǒng)。不是在內(nèi)核啟動完成以后再從磁盤加載到內(nèi)存再進行掛載,而是構建到內(nèi)核鏡像中,所以內(nèi)核啟動完成以后,直接被拷貝到了rootfs
空間,作為初始根文件系統(tǒng),完成掛載真正的根文件系統(tǒng)。
三、initramfs使用
使用如下命令打包initramfs鏡像
# 使用cpio命令進行打包
# -o指輸出 -H newc 指定打包格式為newc,這是initramfs必須指定的打包格式
# gzip是將它進行壓縮,此處可以壓縮也可以不壓縮
find .|cpio -o -H newc | gzip > ~/myinitramfs.cpio.gz
使用如下命令進行解壓查看
# -i 表示指定文件輸入進來 -d表示進行解壓
# --no-absolute-filenames表示不解壓到宿主機根目錄下
zcat hello.cpio.gz | cpio -i -d -H newc --no-absolute-filenames
需要在內(nèi)核配置中進行設置 General setup -->鏡像復制路徑以內(nèi)核源碼根目錄為根目錄
總結:Linux內(nèi)核 --> initrd/initramfs(包含根文件系統(tǒng)的設備驅動) --> Real Root Filesystem
詳細的官方描述文檔:內(nèi)核源碼目錄下 Documentation/filesysytems/ramfs-rootfs-initramfs.txt
嵌入式flash上的文件系統(tǒng)cramfs與squashfs
嵌入式系統(tǒng)上面為了提高安全性與降低文件系統(tǒng)的空間占用。
文件系統(tǒng)一般設置具有如下兩個特點:只讀 + 壓縮。
squashfs
是cramfs
的替代品。
cramfs
全稱compressed ROM filesyatem
,主要用于嵌入式Linux系,簡單與空間高效。
cramfs
最大支持的256MB基本可以滿足嵌入式Linux要求,允許的最大文件系統(tǒng)大小為256+16=272MB,必須設置內(nèi)核的頁大小也為4KB,才可以正確讀取cramfs
文件系統(tǒng)。
cramfs
因為是對頁進行壓縮的,所以查看數(shù)據(jù)的時候先要知道數(shù)據(jù)在哪一頁才能進行解壓縮,這一點要求cramfs
不能對元數(shù)據(jù)進行壓縮,否則無法查看元數(shù)據(jù),不能進行判斷。
ACL
是指訪問控制列表,可以對文件進行權限管理,在嵌入式系統(tǒng)中基本不需要。cramfs
的超級塊與目錄結構不進行壓縮,所謂布局與管理相對來說比較簡單。
這里說的壓縮是指數(shù)據(jù)一直處于被壓縮狀態(tài),只有真正使用的時候才會對數(shù)據(jù)進行解壓縮。
cramfs
在2013年被linus標記為過時的文件系統(tǒng),推薦使用aquashfs
替代cramfs
。
這兩個文件系統(tǒng)都是只讀文件系統(tǒng)
。
嵌入式文件系統(tǒng)jffs/jffs2與yaffs/yaffs2
是專門針對閃存的特性進行設計。
flash閃存的類型:是一種非易失性存儲器,以塊為單元進行擦除和再編程 任何flash的器件的寫入操作只能在空或者已經(jīng)擦除的單元內(nèi)進行,在進行寫入操作之前必須執(zhí)行擦除。分為硬件特性,存取特性,以及兩種特性決定的結論對比。
XIP是指片內(nèi)執(zhí)行功能,代碼可以直接存儲在flash上面,不需要拷貝到內(nèi)存。
針對flash設計的兩種文件系統(tǒng)對比。共性是都是為flash設計的,都是日志文件系統(tǒng)。
yaffs是針對大容量設計的文件系統(tǒng),所以僅僅支持nand flash。
掉電保護,損耗平衡,垃圾回收都是為了保證數(shù)據(jù)可靠,提高使用壽命,以及提高存取效率。
掛載時間與內(nèi)存消耗是重點關注的兩個方面。
掛載時間決定了嵌入式系統(tǒng)的啟動時間,jaffs2會對整個文件系統(tǒng)進行全部盤掃描,將日志節(jié)點掃描出來,在內(nèi)存中創(chuàng)建文件系統(tǒng)的目錄結構。所以掛載時間慢,內(nèi)存消耗多。
舉例說明:
jaffs2掛載16M文件系統(tǒng)需要消耗半分鐘,而yaffs2是立即掛載
jaffs2在128M,頁大小為512K的文件系統(tǒng)上,大約會消耗4M內(nèi)存,而yaffs只需要512K字節(jié)。
Direct使用:
考慮到文件系統(tǒng)的移植性,yaffs2
支持在沒有操作系統(tǒng),沒有VFS
,沒有MTD
驅動的情況下,直接使用yaffs2
,因為yaffs自帶nand flash
驅動,所以移植性,模塊性,擴展性更好,已經(jīng)被移植到UCOSII
上。
ramdisk根文件系統(tǒng)
文件系統(tǒng)與操作系統(tǒng)通過某種形式連接起來(內(nèi)存,flash,網(wǎng)絡)。
將內(nèi)核的指針指向文件系統(tǒng),讀出文件,內(nèi)核就可以啟動成功。
ramdisk稱為內(nèi)存磁盤。
# 設置相關參數(shù)
# root表示啟動的根文件系統(tǒng)在哪個設備
# 設備信息 ram nfs flash
# init進程是什么,內(nèi)核啟動后的第一個可執(zhí)行文件 init =
# 內(nèi)核啟動時,使用那個設備作為控制臺 console=
root = /dev/ram
initrd=<start_addr>,<size>
init=/linuxrc
console=ttymxc0
內(nèi)核可以自解壓.gz
類型的壓縮包。
根文件系統(tǒng)類型
了解完以上知識以后我們知道Linux的根文件系統(tǒng)可以設置為flash相關的文件系統(tǒng)
或內(nèi)存相關的文件系統(tǒng)
或者網(wǎng)絡文件系統(tǒng)
。
這在uboot
中通過指定以下環(huán)境變量來指定。
tootfstype
= jffs2 , yaffs2, squashfs , ubifs 等 。
根文件系統(tǒng)指定在flash上的話,需要指定分區(qū)。
mtdparts
環(huán)境變量 指定flash分區(qū)表。
內(nèi)核中必須有mtd驅動才可以支持識別分區(qū)表。
推薦教程
上面提到的文件系統(tǒng)教程鏈接
鏈接:https://pan.baidu.com/s/1izJq1YETQO2UClwmUZC99Q 提取碼:1quy
來源:于宙,作者:yz001
免責聲明:本文內(nèi)容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!