嵌入式Linux啟動時間優化的秘密之二文件系統
我們繼續上篇沒有講完的嵌入式Linux啟動時間優化方法,本文主要會講文件系統。想看上一篇的請查看本文結尾的鏈接。
1. 文件系統
不同的存儲介質會采用不同的文件系統:
1)塊存儲介質 (包括存儲卡, eMMC):
ext2, ext3,ext4
xfs, jfs,reiserfs
btrfs
f2fs
SquashFS
2)Raw 閃存:
JFFS2
YAFFS2
UBIFS
ubiblock +SquashFS
對於塊文件系統,特性各異:
ext4:最適合較大的分區,良好的讀寫性能。
xfs,jfs,reiserfs:在某些讀或寫場景中也可能很好。
btrfs,f2fs:利用閃存塊設備的特性,可以實現最佳的讀寫性能。
SquashFS:對於只讀分區,最佳掛載時間和讀取性能。非常適合需要只讀的根文件系統。
下面分別介紹各文件系統的詳細特性。
1.1. JFFS2
用於RAW Flash:
掛載時間取決於文件系統的大小:內核必須在掛載時掃描整個文件系統,以讀取屬於每個文件的塊。
需要使用CONFIG_JFFS2_SUMMARY內核選項將此類信息存儲在Flash中。這大大減少了安裝時間。
ARM基准:對於128 MB分區,從16 s到0.8 s。
與YAFFS2和UBIFS相比,讀寫性能相當差。
1.3 YAFFS2
用於RAW Flash:
良好的安裝時間
良好的讀寫性能
缺點:不壓縮,不在主線Linux內核中
1.4. UBIFS
用於RAW Flash:
優勢:
良好的讀寫性能(類似於YAFFS2)
其他優點:更好的磨損均衡(不僅可以在單個分區內,而且可以在整個UBI空間中使用)。
缺點:
不適用於小型分區(元數據開銷過多)。請改用JFFS2或JAFFS2。
掛載時間不是很好,因為初始化UBI需要時間(UBI Attach:在引導時或在用戶空間中運行ubi_attach)。
由Linux 3.7中引入的UBI Fastmap解決。
1.5. UBI Fastmap如何工作
UBI 加載:需要通過掃描所有擦除塊來讀取UBI元數據。時間與存儲空間成正比。
UBI Fastmap將此類信息存儲在幾個閃存塊中(通常在系統關閉期間在UBI分離時),並在引導時找到該信息。
這樣可使UBI附加時間恆定。
如果Fastmap信息無效(例如,不正常的系統關閉),它將退回到掃描狀態(速度較慢,但能保證正確,Fastmap在下次啟動時將恢復)。
詳細信息:Thomas Gleixner的ELCE 2012演講:
http://elinux.org/images/a/ab/UBI_Fastmap.pdf
使用步驟:
使用CONFIG_UBI_FASTMAP配置編譯內核
使用ubi.fm_autoconvert = 1內核參數至少引導一次系統。
以干凈的方式重啟系統
保證如上啟動一次后可以刪除ubi.fm_autoconvert = 1
UBI Fastmap性能測試舉例:
在Linux 3.10的Microchip SAMA5D3 Xplained板(ARM)上測得
UBI空間:216 MB
根文件系統:已使用80 MB(Yocto)
平均加載時間:
無UBI Fastmap,加載時間:968ms
有UBI Fastmap,加載時間:238 ms
可見UBI Fastmap 改善非常顯著!
1.6. ubiblock + SquashFS
對RAW Flash :
ubiblock:位於UBI頂部的只讀塊設備
利用CONFIG_MTD_UBI_BLOCK配置編譯。
允許將SquashFS放在UBI卷上。
引導時間和讀取性能不錯。非常適合於只讀根文件系統。
2. 選取合適的文件系統
RAW Flash :帶有CONFIG_UBI_FASTMAP的UBIFS可能是最佳解決方案。
塊存儲:SquashFS是根文件系統的最佳解決方案,它可以是只讀的。Btrfs和f2fs可能是讀/寫文件系統的最佳解決方案。
更改文件系統類型非常容易,並且對應用程序完全透明。只需嘗試幾個文件系統選項,看看哪個最適合!
不要只關注啟動時間。
對於讀寫性能至關重要的系統,我們建議使用單獨的根文件系統(以加快啟動時間)和數據分區(以實現良好的運行時性能)。
2.1 Initramfs
一個很好的方案是使用非常小的initramfs,以啟動關鍵應用程序,然后切換到最終的根文件系統。
initramfs機制:將根文件系統集成到內核映像中,因此它與內核一起被加載到內存中:
它將文件系統的壓縮存檔集成到內核映像中
變種:壓縮的initramfs固件也可以由bootloader單獨加載。
initramfs在下面兩種情況下非常有用:
快速啟動且非常小的根文件系統。由於文件系統在啟動時已完全加載,因此應用程序啟動也非常快。
作為切換到實際根文件系統之前的中間步驟,該文件位於需要其驅動程序不屬於內核映像的設備(存儲驅動程序,文件系統驅動程序,網絡驅動程序)上。始終在桌面/服務器發行版的內核上使用此選項,以保持內核映像大小合理。
2.2 內存中的initramfs
使用CONFIG_INITRAMFS_SOURCE選項在內核配置級別定義initramfs的內容
可以是包含根文件系統內容的目錄的路徑
可以是cpio歸檔文件的路徑
可以是描述initramfs內容的文本文件
內核構建過程將自動獲取CONFIG_INITRAMFS_SOURCE選項配置的內容,並將根文件系統集成到內核映像中
詳細信息(在內核源文件中):
Documentation/filesystems/ramfs-rootfs-initramfs.txt
DocumentaTIon/early-userspace/README
2.3 用initramfs啟動過程
2.4 initramfs 降低啟動時間
創建盡可能小的最小初始化文件,足以啟動關鍵應用程序,然后使用switch_root切換到最終根文件系統:
使用輕量級的C庫以減小固件大小,建議使用uClibc。
將BusyBox裁剪到最小。甚至可以不用BusyBox直接在C中實現/init。
使用靜態鏈接的應用程序(較少的CPU開銷,較少的庫加載,較小的initramfs(如果根本沒有庫))。Buildroot中用BR2_STATIC_LIBS配置。
2.5 靜態鏈接可執行文件
靜態鏈接的可執行文件對於減小大小(特別是在小型initramfs中)非常有用,並且啟動工作量較少。
如果您將initramfs放在壓縮的內核映像中,請不要對其進行壓縮(啟用CONFIG_INITRAMFS_COMPRESSION_NONE)。
否則默認情況下,您的initramfs數據將被壓縮兩次,內核將更大,並且將花費更多的時間來加載和解壓縮。
在Linux 5.1上的示例在Beagle Bone Black上具有1.60 MB的initramfs(tar存檔大小):這可以將內核大小從4.94 MB減少到4.74 MB(-200 KB),並節省大約170毫秒的啟動時間。