Root filesystem cho thiết bị nhúng¶
Root filesystem (rootfs) là filesystem được kernel mount tại / ngay sau khi khởi động, chứa init, thư viện, ứng dụng và cấu hình. Trên máy tính để bàn, rootfs là phân vùng đọc ghi thông thường. Thiết bị nhúng có các ràng buộc khác: có thể mất điện đột ngột, bộ nhớ flash chịu số lần ghi hữu hạn, thiết bị chạy nhiều năm không có người bảo trì, và firmware cần cập nhật từ xa. Trang này trình bày theo thứ tự: các filesystem thường dùng cho rootfs, mô hình tách rootfs chỉ đọc khỏi vùng dữ liệu ghi được, overlayfs, cách cấu hình trong Yocto và Buildroot, và bố cục phân vùng khi cần cập nhật A/B.
Các filesystem thường dùng cho rootfs¶
| Filesystem | Đặc điểm | Thường dùng khi |
|---|---|---|
| ext4 | Đọc ghi, có journal, chạy trên block device (eMMC, SD, SSD) | Rootfs đơn giản trên eMMC hoặc SD, ưu tiên dễ phát triển |
| squashfs | Nén, chỉ đọc. Tài liệu kernel nêu đây là filesystem phù hợp với hệ thống bị giới hạn về block device và bộ nhớ, ví dụ hệ nhúng, cần overhead thấp | Rootfs cố định, cần giảm dung lượng và cần ký hoặc kiểm tra toàn vẹn cả image |
| UBIFS | Đọc ghi, chạy trên volume UBI của raw NAND, xem UBI và UBIFS | Thiết bị dùng raw NAND |
| initramfs (cpio) | Rootfs nằm trong RAM, được kernel giải nén khi boot | Thiết bị nhỏ hoặc tầng khởi động trung gian trước khi chuyển sang rootfs thật |
Squashfs là filesystem chỉ đọc có nén, đóng gói bằng công cụ mksquashfs chứ không ghi trực tiếp từng file. Kích thước block mặc định là 128 KiB và có thể lên tới 1 MiB. Thuật toán nén gồm zlib, lzo, xz và zstd, tùy bản kernel và công cụ.
Mọi lựa chọn trên đều là lựa chọn cho phần chứa hệ thống. Khi thiết bị cần lưu cấu hình hoặc dữ liệu, cần một vùng ghi được riêng, như trình bày ở các mục sau.
Tách rootfs chỉ đọc khỏi vùng dữ liệu¶
Mô hình phổ biến trên thiết bị sản phẩm là rootfs chỉ đọc cộng với một phân vùng dữ liệu đọc ghi. Tài liệu của Digi Embedded Yocto nêu ba lợi ích của cách làm này: tách thay đổi của người dùng khỏi cấu hình hệ thống, factory reset bằng cách xóa phân vùng dữ liệu, và ký rồi xác thực được image rootfs lúc boot vì image không thay đổi.
Rootfs chỉ đọc không nghĩa là hệ thống không ghi được gì. Một số thư mục cần ghi lúc chạy:
/etc: cấu hình có thể được thay đổi bởi người dùng hoặc bởi ứng dụng (địa chỉ mạng, chứng chỉ)./var,/tmp: trạng thái và file tạm. Thường mounttmpfs(filesystem trong RAM) để không ghi lên flash./homehoặc thư mục dữ liệu ứng dụng: nằm trên phân vùng dữ liệu.
Overlayfs¶
Overlayfs hợp nhất hai cây thư mục thành một: lớp dưới (lowerdir) và lớp trên (upperdir). Khi một tên tồn tại ở cả hai lớp, đối tượng ở lớp trên được thấy, còn đối tượng ở lớp dưới bị che. Với hai thư mục cùng tên, kết quả là thư mục hợp nhất. Theo tài liệu kernel, lớp dưới có thể là bất kỳ filesystem nào mà Linux hỗ trợ và không cần ghi được. Nếu bỏ upperdir và workdir, overlay ở chế độ chỉ đọc.
Cú pháp mount theo tài liệu kernel:
Các ràng buộc của hai thư mục ghi được:
workdirphải là thư mục rỗng nằm trên cùng filesystem vớiupperdir.- Filesystem chứa
upperdirphải hỗ trợ extended attribute dạngtrusted.*và trả vềd_typehợp lệ trongreaddir. Vì vậy NFS không phù hợp làmupperdir.
Ví dụ phủ phần ghi được lên /etc, với phân vùng dữ liệu đã mount tại /data:
mkdir -p /data/overlay/etc/upper /data/overlay/etc/work
mount -t overlay overlay \
-o lowerdir=/etc,upperdir=/data/overlay/etc/upper,workdir=/data/overlay/etc/work \
/etc
Thử nghiệm trên một cây thư mục tạm (không phải trên board) cho kết quả đúng như mô tả: sửa a.conf có sẵn và tạo b.conf mới đều xuất hiện trong thư mục hợp nhất và trong upperdir, trong khi lowerdir giữ nguyên nội dung cũ. Lần ghi đầu tiên vào một file của lớp dưới sao chép (copy-up) file đó sang lớp trên.
Todo
Chưa kiểm chứng trên board thật: độ bền của upperdir khi mất điện đột ngột và mức mòn flash khi ứng dụng ghi thường xuyên vào /etc. Cần thử cắt nguồn lặp lại trên phân vùng dữ liệu ext4 và UBIFS.
Cấu hình trong Yocto¶
Yocto có IMAGE_FEATURE read-only-rootfs. Theo tài liệu Digi, tính năng này làm Yocto thay đổi một số recipe để chúng không sửa file trong rootfs lúc chạy. Định dạng image do IMAGE_FSTYPES quyết định; bản dựng của Digi tạo ra image squashfs.
Để có overlay cho /etc, Yocto có IMAGE_FEATURE overlayfs-etc. Cấu hình mẫu trong conf/local.conf:
EXTRA_IMAGE_FEATURES += "read-only-rootfs overlayfs-etc"
IMAGE_FEATURES:remove = "package-management"
OVERLAYFS_ETC_MOUNT_POINT = "/mnt/data"
OVERLAYFS_ETC_DEVICE = "/dev/mmcblk0p7"
OVERLAYFS_ETC_FSTYPE = "ext4"
Ba biến OVERLAYFS_ETC_* chỉ định điểm mount, thiết bị và loại filesystem của phân vùng dữ liệu chứa upperdir. Với thiết bị dùng UBI, thiết bị có dạng ubi1:data và loại filesystem là ubifs. Gỡ package-management vì trình quản lý gói cần ghi vào rootfs.
Cấu hình trong Buildroot¶
Buildroot chọn định dạng image bằng các tùy chọn BR2_TARGET_ROOTFS_*, ví dụ BR2_TARGET_ROOTFS_SQUASHFS và BR2_TARGET_ROOTFS_UBIFS. Danh sách định dạng nằm trong thư mục fs/ của source tree, xem Buildroot.
Phân biệt hai khái niệm overlay
BR2_ROOTFS_OVERLAY của Buildroot là cây thư mục được sao chép đè lên rootfs ở thời điểm build, không liên quan đến overlayfs của kernel. Xem mục "Tùy biến rootfs" trong trang Buildroot.
Chỉ định rootfs trên kernel command line¶
Kernel nhận rootfs qua tham số root= và rootfstype=. Với rootfs chỉ đọc, thêm ro. Bảng ví dụ cho eMMC, UBIFS và squashfs trên NOR nằm ở mục Mount rootfs từ flash.
Khi rootfs là squashfs và cần overlay cho /etc, overlay phải được mount rất sớm, trước khi các service đọc cấu hình. Việc này thường do initramfs hoặc script init sớm đảm nhận. Trong Yocto, tính năng overlayfs-etc đã bao gồm bước này.
Bố cục phân vùng khi cập nhật A/B¶
Khi dùng cập nhật A/B (hai bản rootfs luân phiên, xem OTA Update), bố cục thường gồm phân vùng boot, hai phân vùng rootfs và một phân vùng dữ liệu dùng chung:
| Phân vùng | Nội dung | Ghi được lúc chạy |
|---|---|---|
| boot | Bootloader, biến môi trường, kernel và DTB | Chỉ khi cập nhật |
| rootfs A | Rootfs đang chạy | Không |
| rootfs B | Rootfs bản cập nhật | Chỉ khi cập nhật |
| data | Cấu hình, upperdir của overlay, dữ liệu ứng dụng |
Có |
Phân vùng dữ liệu nằm ngoài vùng bị thay thế khi cập nhật, nên cấu hình và dữ liệu người dùng được giữ nguyên qua các lần cập nhật. Cần kiểm tra tương thích định dạng dữ liệu giữa phiên bản cũ và mới của ứng dụng.
Liên quan¶
- Flash Storage (MTD, MMC) (Linux Kernel): UBI, UBIFS và tham số
root=cho từng loại bộ nhớ. - Chọn bộ nhớ non-volatile: chọn loại bộ nhớ cho board.
- Kernel Command Line: các tham số
root,rootfstype,ro,rootwait. - OTA Update: cập nhật A/B và rollback.
- Yocto, Buildroot: tạo image rootfs.
- Init system: tiến trình đầu tiên mount các filesystem còn lại.
Tài liệu tham khảo¶
- Kernel docs: Overlay Filesystem
- Kernel docs: Squashfs 4.0 Filesystem
- Digi Embedded Yocto: Read-only root file system:
read-only-rootfs,overlayfs-etc, các biếnOVERLAYFS_ETC_*. - Buildroot manual: các tùy chọn
BR2_TARGET_ROOTFS_*,BR2_ROOTFS_OVERLAY.