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