我正在开发一款带有 arm cortex A9 的嵌入式设备。内核版本为 4.16.0,由 buildroot 2018.05 生成。存储内存是一个具有多个分区的 mmc。U-boot 读取一个分区中的 uImage 并启动内核。文件系统包含在内核映像中,并在启动时加载到 initramfs 中(配置:BR2_TARGET_ROOTFS_INITRAMFS)。
我想使用 overlayfs 将文件夹(在 mmc 中)用作“用户”文件系统,并挂载到/
。
我已成功尝试通过将这些行添加到以下目录来覆盖/etc
名为的目录:/data/etc
/etc/fstab
/dev/mmcblk0p1 /data auto defaults 0 1
overlay /etc overlay x-systemd.requires=/data,lowerdir=/etc,upperdir=/data/etc,workdir=/data/work/etc 0 1
这是可行的,但覆盖是在 systemd 启动其服务后安装的。因此,例如网络配置是 uImage 中的配置,而不是我的user
文件系统中的配置。我想在启动 systemd 之前安装覆盖,就在/
安装之后。
我的理解是,在启动时,系统会在 RAM 中创建第一个内存空间,然后在其中提取 cpio 映像。然后/
将其安装在那里,系统启动第一个程序:systemd:/sbin/init
PID 为 1。我的理解正确吗?
我读了很多文章和问答网站,但我仍然不明白在 systemd 启动之前,我必须在哪里进行更改才能在启动时执行覆盖。包含该mount /
操作的文件是什么?
答案1
我的理解是,在启动时,系统会在 RAM 中创建第一个内存空间,然后在其中提取 cpio 映像。然后 / 会挂载在那里,系统会启动第一个程序:systemd:/sbin/init,PID 为 1。我的理解正确吗?
接近但不完全正确,你错过了中间的几个步骤。如果你使用 initramfs,实际顺序是:
Linux 挂载内存空间(“tmpfs”文件系统)在
/
并提取其中的 cpio 映像。Linux 运行
/init
现有的二进制文件在 cpio 图像中. 这将成为 PID 1。initramfs init 进程将您的主 rootfs 挂载到某个地方,例如
/new
或/real
。通常它不使用 fstab,而只使用内核命令行中提供的信息。initramfs init 进程使用 pivot_root() 和 chroot() 函数,以便将 rootfs 挂载在
/
。(原始内存中的 / 变得无法访问。)initramfs init 进程从 执行“真正的” init 系统(即 systemd)
/sbin/init
。由于它使用 exec() 来执行此操作,因此前后保持相同的 PID 1。Systemd 开始启动服务并挂载 /etc/fstab 条目。
因此,对于您的情况,您需要编辑 initramfs,以便它在步骤 3-4 中直接转到 overlayfs,而不是使用“原始”根分区。这应该不难,因为 initramfs /init 文件通常是一个基本的 shell 脚本。