精通init ramfs构建step by step (六)

时间:2022-02-28 16:33:51

二十、switch_root 命令

  除了基于init ramfs的系统(如第四节的mini linux),通常init ramfs都是为安装最终的根文件系统做准备工作,它的最后一步需要安装最终的根文件系统,然后切换到新根文件系统上去。以往的基于ramdisk 的initrd 使用pivot_root命令切换到新的根文件系统,然后卸载ramdisk。但是init ramfs是rootfs,而rootfs既不能pivot_root,也不能umount。为了从init ramfs中切换到新根文件系统,需要作如下处理:

  (1)删除rootfs的全部内容,释放空间

  find -xdev / -exec rm '{}' ';'

  (2)安装新的根文件系统,并切换

  cd /newmount; mount --move . /; chroot .

  (3)把stdin/stdout/stderr 附加到新的/dev/console,然后执行新文件系统的init程序

  上述步骤比较麻烦,而且要解决一个重要的问题:第一步删除rootfs的所有内容也删除了所有的命令,那么后续如何再使用这些命令完成其他步骤?busybox的解决方案是,提供了switch_root命令,完成全部的处理过程,使用起来非常方便。

  switch_root命令的格式是:

  switch_root [-c /dev/console] NEW_ROOT NEW_INIT [ARGUMENTS_TO_INIT]

  其中NEW_ROOT是实际的根文件系统的挂载目录,执行switch_root命令前需要挂载到系统中;NEW_INIT是实际根文件系统的init程序的路径,一般是/sbin/init;-c /dev/console是可选参数,用于重定向实际的根文件系统的设备文件,一般情况我们不会使用;而ARGUMENTS_TO_INIT则是传递给实际的根文件系统的init程序的参数,也是可选的。

  需要特别注意的是:switch_root命令必须由PID=1的进程调用,也就是必须由init ramfs的init程序直接调用,不能由init派生的其他进程调用,否则会出错,提示:

  switch_root: not rootfs

  也是同样的原因,init脚本调用switch_root命令必须用exec命令调用,否则也会出错,提示:

  switch_root: not rootfs

  二十一、实践:用init ramfs安装CLFS根文件系统

  现在实践一下switch_root命令,用它切换一个CLFS的根文件系统硬盘分区。我的CLFS安装在/dev/sda8硬盘分区,我们就以此为例说明。

  我们还是在以前的image目录中构建

  (1)改写init脚本

  #!/bin/sh

  mount -t proc proc /proc

  mount -t sysfs sysfs /sys

  mdev -s

  mount /dev/sda8 /mnt (注意:为了简单,我们直接把CLFS分区写死在init脚本中了)

  exec switch_root /mnt /sbin/init

  (2)生成新的initrd

  按上一节“精通init ramfs构建step by step (五):initrd”描述的cpio命令生成新的initrd。

  (3)把新的initrd拷贝到CLFS分区的/boot目录下,改名为clfs-initrd

  (4)在GRUB的menu.lst配置文件中增加一个启动项

  #test for init ramfs of CLFS

  title test for init ramfs of CLFS (on /dev/sda8)

  root (hd0,7)

  kernel /boot/clfskernel-2.6.17.13 (注意:并没有向内核传递root参数信息)

  initrd /boot/clfs-initrd

  全部做完后,重启机器,选择 test for init ramfs of CLFS 启动项,机器顺利进入了CLFS系统,我们构建的init ramfs用switch_root命令完成了CLFS实际根文件系统的安装和切换。