在使用嵌入式?Linux?系統的時,會出現由于設備意外斷電引起文件系統損壞而最終使該設備無法啟動的現象。為了應對這種情況,通常會從硬件設計如采用備用電源,無論是鋰電池還是超級電容等,或者從系統軟件設上加以規避。本文接下來將介紹如何使用?squashfs?只讀文件系統制作?Linux?系統文件,并采用?overlayfs?為用戶目錄增加可寫權限。演示采用?Colibri iMX6?計算機模塊,該方法同樣也適用于?Toradex?其他產品,如?iMX8?計算機模塊。
Squashfs?是一種只讀壓縮文件系統,通常被用于數據備份或者系統資源受限的計算機系統上使用,如?Linux?發行版的?LiveCD,OpenWRT?系統也采用?squashfs。OverlayFS?一個結合其他文件系統的聯合掛載,將多個掛載點疊加為一個目錄。常見的應用是在一個只讀的分區上疊加可讀寫的另一個分區。嵌入式?Linux?設備通常的功能都是被設計好的,極少需要在后期安裝其他軟件或更改?Linux?系統軟件,更多的是更新設備應用程序和相關數據。因此基于?squashfs?的只讀文件系統,結合?overlayfs?為用戶應用和數據提供讀寫操作,能夠提高嵌入式?Linux?文件系統可靠性。
在?Colibri iMX6?的?eMMC?上我們將使用以下分區規劃。BootFS?為?FAT32?格式,該分區上包含?Linux?內核文件,device tree?等啟動文件,如果是?iMX8,則還包含一些其他固件文件。該分區通常只在文件系統燒寫階段被寫入。RootFS?分區是?Linux?運行的文件系統,usr, bin, lib, etc, home?等目錄都在上面。一般該分區是EXT3,EXT4?格式,支持文件的寫入和刪除。而文件系統的損壞也常發生于此,最終導致設備啟動失敗。因此我們這里會采用只讀格式的?squashfs?。UserData?是能夠讀寫的?EXT4?分區。該分區通過?overlayfs?會被掛載到原本位于只讀?squashfs??中的?/home/root?目錄。用戶應用可以毫無察覺得使用該目錄,在上面寫入和刪除文件,但不破壞只讀?squashfs?文件系統,所有的操作都會被轉移到?UserData?分區上。用戶的應用也會存在?UserData?分區上,啟動的時候從這里加載應用程序。該分區是可寫的,所有這上面的文件是可以被更新。
下面我們會具體說明如何在?Yocto?環境生成符合上面規劃的?BSP?,并通過?Toradex Easy Installer?工具實現這些分區和寫入文件。
首先需要在?Yocto?環境中生成?squashfs?格式的系統文件?rootfs。修改?build/conf/local.conf?,結尾添加以下內容。
------------------------------------
IMAGE_FSTYPES_append = " squashfs"
------------------------------------
默認?Linux?內核配置下?squahfs?是通過加載內核驅動模塊實現對其支持,而模塊驅動文件位于?rootfs?中,為了保證?Linux?內核在啟動時能夠正確處理該格式,需要將?squahfs?內核驅動模塊配置為靜態驅動,直接編譯進內核中。為內核配置的文件系統支持添加?squahfs?和?overlay?格式。
------------------------------------
$ MACHINE=colibri-imx6 bitbake -c menuconfig virtual/kernel
→?File systems
<*> Overlay filesystem support
→?File systems?→?Miscellaneous filesystems
<*>?? SquashFS 4.0 - Squashed file system support?
------------------------------------
EXT4?格式的?UserData?分區會通過?overlay?機制掛載到只讀的?rootfs?上的?/home/root,但這之前需要通過?fstab?將該分區掛載到系統中,/dev/mmcblk0p3 -> /media/data-> /home/root。在?Yocto?中,layers/meta-toradex-demos/recipes-core/base-files/base-files/fstab?會被編譯到?Colibri IMX6 BSP?中,在該文件中添加:
------------------------------------
/dev/mmcblk0p3?????? /media/data???????? auto?????? defaults,sync,noauto? 0? 0
------------------------------------
然后再添加一個開機自啟動腳本,將??/media/data?使用?overlay掛載到?/home/root。?在?layers/meta-toradex-bsp-common/recipes-core目錄中添加?mount-overlayfs?文件夾,里面包含編譯需要的?bb?文件和?systemd service。mount-overlayfs.bb?中?install -d ${D}/media/data?會在?/media?目錄中創建?data?文件夾,FILES_${PN} = "/media/data"?將該空文件夾添加到?BSP?中。?mount-overlayfs.service?通過?RequiresMountsFor?保證?/media/data?目錄通過?fstab?掛載后才運行。Overlay?的目錄結構如下,lowerdir?為/home/root upperdir?為?/media/data/home/root/upper,workdir?為?/media/data/home/root/work。這樣應用可以在?/home/root?下直接讀寫文件,overlayfs?對應用和用戶都是透明的。
------------------------------------
[Service]
Type=simple
ExecStart=/bin/sh -c 'mount -t overlay -o lowerdir=/home/root,upperdir=/media/data/home/root/upper,workdir=/media/data/home/root/work overlay /home/root'
------------------------------------
在?build/conf/local.conf?中將?mount-overlayfs?添加到?BSP?中。
------------------------------------
IMAGE_INSTALL_append = " mount-overlayfs"
------------------------------------
由于?rootfs?是只讀格式,無法像之前一樣直接在開發板上運行?systemctl?命令添加開機自啟動腳本。我們需要像上面一樣,在?Yocto?中增加一個?test-app?來開機自動運行位于?UserData?分區(該分區通過?overlay?會被最終掛載到?/home/root?目錄)上的測試程序?test。在?layers/meta-toradex-bsp-common/recipes-core目錄中添加?test-app?文件夾,里面包含編譯需要的?bb?文件和?systemd service。
在?build/conf/local.conf?中將?test-app?添加到?BSP?中。
------------------------------------
IMAGE_INSTALL_append = " mount-overlayfs test-app"
------------------------------------
至此我們已經通過修改?Yocto?能夠生成所需結構的BSP,執行下面命令完成編譯任務。
------------------------------------
$ MACHINE=colibri-imx6 bitbake tdx-reference-minimal-image
------------------------------------
在?build/deploy/images/colibri-imx6?有相關文件生成,我們需要下面兩個文件,文件名字中的時間戳對應具體編譯的日期。
Colibri-iMX6_Reference-Minimal-Image-Tezi_5.1.0-devel-20201112022057+build.0.tar
Colibri-iMX6_Reference-Minimal-Image.rootfs.squashfs
解壓?Colibri-iMX6_Reference-Minimal-Image-Tezi_5.1.0-devel-20201112022057+build.0.tar。因為rootfs?是?squahfs?格式,需要使用定制的?boot.src?來啟動。
------------------------------------
$ cd ~/
$ tar vxf Colibri-iMX6_Reference-Minimal-Image-Tezi_5.1.0-devel-20201112022057+build.0.tar
$ cd Colibri-iMX6_Reference-Minimal-Image-Tezi_5.1.0-devel-20201112022057+build.0
$ tar vxf Reference-Minimal-Image-colibri-imx6.bootfs.tar.xz
------------------------------------
修改其中的?emmcargs_set?參數。
------------------------------------
env set emmcargs_set 'env set rootfsargs root=/dev/mmcblk0p2 rootfstype=squashfs ro rootwait'
------------------------------------
可以使用該?boot.cmd?直接生成對應的?boot.src,?替換解壓目錄中同名文件,?重新打包?Reference-Minimal-Image-colibri-imx6.bootfs.tar.xz
------------------------------------
$ cd Reference-Minimal-Image-colibri-imx6.bootfs
$ rm boot.src
$ mkimage -A arm -O linux -T script -C none -a 0 -e 0 -n "Distro boot script" -d boot.cmd boot.scr
$ cd ..
$ tar cJf Reference-Minimal-Image-colibri-imx6.bootfs.tar.xz -C Reference-Minimal-Image-colibri-imx6.bootfs .
------------------------------------
將?squashfs?的?rootfs?文件系統復制到?Colibri-iMX6_Reference-Minimal-Image-Tezi_5.1.0-devel-20201112022057+build.0?目錄中。
------------------------------------
$ cp Colibri-iMX6_Reference-Minimal-Image.rootfs.squashfs Colibri-iMX6_Reference-Minimal-Image-Tezi_5.1.0-devel-20201112022057+build.0
------------------------------------
接下來創建需要復制到?UserData?分區中的文件。如上面提到的?overlay?掛載需要有對應目錄結構,依次創建以下目錄,并將測試程序?test?復制到?upper?目錄中。這里的測試程序?test?是一個非常簡單的?C?應用,它會輸出“Hello Toradex!”到系統日志中。
------------------------------------
$ cd ~/Colibri-iMX6_Reference-Minimal-Image-Tezi_5.1.0-devel-20201112022057+build.0
$ mkdir rootfs
$ cd rootfs
$ mkdir -p home/root/upper
$ mkdir -p home/root/work
$ cp ~/test home/root/upper
$ tree
------------------------------------
打包為?rootfs.tar.xz。
------------------------------------
$ cd ..
$ sudo tar cJf rootfs.tar.xz -C rootfs .
------------------------------------
修改?image.json?文件,在blockdevs?中增加?RAW?格式分區用于直接寫入?squashfs?系統文件,以及?EXT4?格式的DATA分區用于寫入上面生成的?rootfs.tar.xz。
Colibri-iMX6_Reference-Minimal-Image-Tezi_5.1.0-devel-20201112022057+build.0?目錄下最終包含以下文件。
將上面的?BSP?通過?Toradex Easy Installer?重新安裝到?Colibri iMX6?上,安裝的時候注意需要點擊?Erase?擦除?eMMC?上的內容。
燒寫后重啟模塊??梢酝ㄟ^?mount?命令查看掛載分區的情況。
------------------------------------
root@colibri-imx6:~# mount
/dev/mmcblk0p2 on / type squashfs (ro,noatime)
……
/dev/mmcblk0p3 on /media/data type ext4 (rw,relatime,sync)
overlay on /home/root type overlay (rw,relatime,lowerdir=/home/root,upperdir=/media/data/home/root/upper,workdir=/media/data/home/root/work)
------------------------------------
mmcblk0p2?為寫入?squashfs?只讀文件系統的分區,例如在?/etc?目錄無法創建文件。
------------------------------------
root@colibri-imx6:/etc# mkdir test-folder
mkdir: can't create directory 'test-folder': Read-only file system
------------------------------------
EXT4?格式的?/dev/mmcblk0p3?分區上是用戶文件,被掛載到?/media/data。而?/home/root?會通過?overlay?具有可讀寫權限。
------------------------------------
root@colibri-imx6:~# cd ~/
root@colibri-imx6:~# pwd
/home/root
root@colibri-imx6:~# mkdir test-folder
root@colibri-imx6:~# ls
test???????? test-folder
root@colibri-imx6:~# ls -lh
-rwxrwxr-x??? 1 1000???? 1000?????? 11.3K Nov 11? 2020 test
drwxr-xr-x??? 2 root???? root??????? 4.0K Feb? 7 16:25 test-folder
------------------------------------
位于?UserData?上的測試程序?test??也在開機的時候自動運行。
------------------------------------
root@colibri-imx6:~# journalctl -u test-app
-- Logs begin at Fri 2020-02-07 15:50:53 UTC, end at Fri 2020-02-07 16:11:49 UTC. --
Feb 07 15:50:57 colibri-imx6 systemd[1]: Started start a demo on overlay mount folder.
Feb 07 15:50:57 colibri-imx6 test[456]: Hello Toradex!
Feb 07 15:50:57 colibri-imx6 systemd[1]: test-app.service: Succeeded.
------------------------------------
總結
上面我們演示結合使用?squashfs?和?overlay,將系統文件放在一個只讀分區,把讀寫操作在單獨的分區上進行。降低系統文件因意外斷電受損從而導致無法啟動的風險。在使用只讀?squashfs?只讀文件系統時需要保證?rootfs?盡量精簡,建議在?Reference-Minimal-Image?基礎上構建用戶自己的?BSP,甚至對其進行裁剪。
審核編輯:黃飛
評論
查看更多