我知道它们是两个不同的东西,但是实际的 Linux 内核和 rootFS 文件系统之间有什么区别,尤其是在内存中的位置和更新方面?
内核通常是一个图像文件(如zImage
)。在 ARM 系统中,内核也需要设备树文件,但我们暂时避免使用它。反过来,RootFS 是一个文件系统,其中包含您的所有文件/
,如二进制文件 ( init
, bash
)、配置文件 ( /etc
)、用户主目录等。有时 RootFs 包含内核映像文件,有时不包含,取决于您的特定系统。
关于分区,为什么内核和 rootFS 几乎总是在不同的分区上?内核代码不会存储在 rootFS 本身中吗?那么它们在内存中的不同分区上如何呢?
您问题的关键是考虑引导加载程序(如 U-Boot 或 GRUB)。一旦您了解了引导加载程序中操作系统引导过程的工作原理,答案就会自动显现。正如您所提到的,存在不同的分区方案,这导致启动过程中的差异。实际上,有很多不同的引导方案。让我们回顾一下其中的一些,希望它能解释您想知道的内容。
- 不同分区上的内核和 rootfs。在这种情况下,引导加载程序通常将内核映像读取到 RAM,通过内核 cmdline(通过
root=
参数)传递 rootfs 分区。然后 bootloader 开始执行内核,内核正在从root=
参数指定的分区挂载 rootfs。
- 内核映像位于 rootfs 内。在这种情况下,引导加载程序应该知道内核映像的确切位置(例如在 中
/boot/zImage
)。Bootloader 知道 rootfs FS 格式(例如 ext4),/boot/zImage
从 rootfs 读取到 RAM。然后像上一项一样继续执行。
- 内核映像和 rootfs 通过网络(例如 TFTP)传递。在这种情况下,有时,rootfs 被放入 RAM 并作为 ramdisk(从 RAM)安装。在这种情况下不使用持久存储,并且对 rootfs 的任何更改都将在重新启动后丢失。另一个网络案例是通过 NFS 挂载 rootfs 时,将使用服务器上的持久存储(用户可以透明地查看)。
现在关于更新,我一直在研究一个声称可以进行完整内核映像更新的 OTA 更新框架。它为 rootFS 使用两个单独的分区。如果更新一个 rootFS 分区出现问题,它可以退回到正常工作的 rootFS 分区,这是有意义的。但是,这实际上是如何更新内核的呢?我不明白。
在更新方面,使用哪种方案(1)或(2)没有什么不同。你所说的被称为(至少在 Android 中)A/B 无缝更新,这意味着两个分区(A 和 B)用于存储相同的图像(例如旧的 rootfs 和新的 rootfs)。您需要了解只更新没有内核的 rootfs 是可以的。内核开发中有一条规则是这样的:“我们不会破坏用户空间”。这意味着您可以依靠不同版本的内核来运行相同的用户空间,或者您可以依靠一个内核版本来运行不同的用户空间。
所以它更像是架构问题:你想更新系统中的内核吗?如果是,那么您需要为内核提供两个不同的分区,为 rootfs 提供两个分区。或者,您可以将内核映像和 rootfs 放在同一个分区中(例如,参见Android 启动映像格式),并提供第二个分区进行更新。