让 busybox switch_root 工作时出现问题

让 busybox switch_root 工作时出现问题

我正在开发一个使用 initramfs 启动的嵌入式 ARM Linux 系统。 (这是一对夫妇的一些背景早些时候 问题,如果您有兴趣。)到目前为止,部分感谢此处收到的帮助,我可以通过带有嵌入式 initramfs 的 TFTP 启动内核。 MMC 驱动程序检测到包含新根文件系统的 SD 卡,然后我可以挂载该文件系统。但是,我无法完成最后一步,即使用 busybox switch_root 切换到 SD 卡上的文件系统。

在 initramfs shell 提示符下,我认为这应该使内核切换到新的文件系统:

switch_root -c /dev/console /mnt/root /sbin/init.sysvinit 

然而,它只是让 busybox(switch_root 的别名)打印它的手册页,如下所示:

/ # switch_root -c /dev/console /mnt/root /sbin/init.sysvinit 
BusyBox v1.17.4 (2010-12-08 17:01:07 EST) multi-call binary.

Usage: switch_root [-c /dev/console] NEW_ROOT NEW_INIT [ARGS]

Free initramfs and switch to another root fs:
chroot to NEW_ROOT, delete all in /, move NEW_ROOT to /,
execute NEW_INIT. PID must be 1. NEW_ROOT must be a mountpoint.

Options:

-c DEV  Reopen stdio to DEV after switch

我认为 -c 选项是正确的,因为它与示例中包含的内容相同,并且 /dev/console 存在。

/ # ls -l /dev
total 0
crw-r--r--    1 0        0           5,   1 Jan  1 00:28 console
brw-r--r--    1 0        0           7,   0 Dec 21  2010 loop0
brw-r--r--    1 0        0         179,   0 Dec 21  2010 mmcblk0
brw-r--r--    1 0        0         179,   1 Dec 21  2010 mmcblk0p1
brw-r--r--    1 0        0         179,   2 Dec 21  2010 mmcblk0p2
brw-r--r--    1 0        0         179,   3 Dec 21  2010 mmcblk0p3
brw-r--r--    1 0        0         179,   4 Dec 21  2010 mmcblk0p4

/mnt/root 也存在。

/ # ls /mnt/root
bin         etc         linuxrc     mnt         sys         var
boot        home        lost+found  proc        tmp
dev         lib         media       sbin        usr

init 可执行文件存在:

/ # ls -lh /mnt/root/sbin/
<snip>
lrwxrwxrwx    1 0        0             19 Dec 21  2010 init -> /sbin/init.sysvinit
-rwxr-xr-x    1 0        0          22.8K Dec 21  2010 init.sysvinit

但这里有一些奇怪的事情:

/mnt/root/sbin # pwd
/mnt/root/sbin
/mnt/root/sbin # ls -l | grep init.sysvinit
lrwxrwxrwx    1 0        0               19 Dec 21  2010 init -> /sbin/init.sysvinit
-rwxr-xr-x    1 0        0            23364 Dec 21  2010 init.sysvinit
/mnt/root/sbin # ./init.sysvinit 
/bin/sh: ./init.sysvinit: not found
/mnt/root/sbin # /mnt/root/sbin/init.sysvinit 
/bin/sh: /mnt/root/sbin/init.sysvinit: not found

这真是令人费解。我不确定我哪里错了。我查看了来源,位于http://git.busybox.net/busybox/tree/util-linux/switch_root.c?id=1_17_4

它不仅仅是 init.sysvinit 可执行文件。我无法从 SD 卡执行任何操作。例如:

/mnt/root/bin # ./busybox 
/bin/sh: ./busybox: not found
/mnt/root/bin # /mnt/root/busybox 
/bin/sh: /mnt/root/busybox: not found
/mnt/root/bin # ls -l | grep "2010 busybox"
-rwxr-xr-x    1 0        0           462028 Dec 21  2010 busybox

有人知道这里出了什么问题吗?我认为挂载卡 noexec 可能会出现问题,但我相信 exec 是默认值,并且我尝试在挂载时显式传递 exec 选项,但没有成功。

答案1

switch_root在命令行上不起作用的原因是 busybox 中的以下代码:

    if (st.st_dev == rootdev || getpid() != 1) {
        // Show usage, it says new root must be a mountpoint
        // and we must be PID 1
        bb_show_usage();
    }

你不是 PID 1,所以你陷入了这个困境bb_show_usage。这意味着switch_rootinitramfs init 脚本中的命令应该switch_rootexec. IE

exec switch_root ...

“未找到”错误的另一个问题可能是因为未找到可执行文件所需的共享库,因为 initramfs 根文件系统没有它们。如果您可以switch_root使用exec,那么“未找到”错误可能会消失。

答案2

switch_root -c /dev/console /mnt/root /mnt/root/sbin/init.sysvinit为我工作。我有同样的问题,但switch_root -c /dev/console /mnt/root /sbin/init.sysvinit没有工作。

很抱歉没有人为我工作。

我制作了一个 ext2 文件系统,复制了静态构建的 busybox 及其所有软链接。 busybox 有粘性位。(-rwsr-sr-x 权限)。我有一个 /linuxrc,而 /etc/ 目录中没有太多内容。我使用以下命令从 ext2 文件系统制作图像。

mkimage -C gzip -A ppc -O linux -T ramdisk -a 0x2000000 -n "ramdisk" -d initrd-ext2 initrd.img

我将 initrd.img 作为单独的文件保留在 /boot/ 中,并且不是内核的一部分。

linuxrc的内容是

#!/bin/sh (也尝试过#!/bin/busybox sh)

mkdir -p /proc /dev /sys /mnt /tmp
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mknod /dev/misc/rtc0 c 254 0
mdev -s
mkdir -p /new_root
mount /dev/mmcblk0p2 /new_root
exec switch_root -c /dev/console /new_root /sbin/init

我的内核被正确加载,initrd.img 也被加载,linuxrc 被执行,但最后 switch_root 提供了使用帮助。

但随后我的系统继续启动并加载新的 rootfs。以下是顺序。

RAMDISK: ext2 filesystem found at block 0
RAMDISK: Loading 10240KiB [1 disk] into ram disk... done.
VFS: Mounted root (ext2 filesystem) on device 1:0.
Starting initramfs boot...

Waiting 5 seconds for devices to settle...

kjournald starting.  Commit interval 5 seconds
EXT3 FS on mmcblk0p2, internal journal
EXT3-fs: mounted filesystem with writeback data mode.
BusyBox v1.21.0.git (2012-10-17 00:34:21 PDT) multi-call binary.

Usage: switch_root [-c /dev/console] NEW_ROOT NEW_INIT [ARGS]

Free initramfs and switch to another root fs:
chroot to NEW_ROOT, delete all in /, move NEW_ROOT to /,
execute NEW_INIT. PID must be 1. NEW_ROOT must be a mountpoint.

        -c DEV  Reopen stdio to DEV after switch

VFS: Mounted root (ext3 filesystem) on device 179:2.
Trying to move old root to /initrd ... /initrd does not exist. Ignored.
Unmounting old root
Trying to free ramdisk memory ... okay
Freeing unused kernel memory: 200k init
INIT: version 2.86 booting
Please wait: booting...
mount: sysfs already mounted or /sys busy
mount: according to mtab, sysfs is already mounted on /sys
Starting udev
udev: starting version 154
Root filesystem already rw, not remounting
Caching udev devnodes
  1. 按上述顺序退出 initrd.img 后我的内存是否被释放?

  2. 如果我不在 linuxrc 末尾执行 switch_root 并只是退出会怎么样?这不会把我的内存从旧的 initrd img 中解放出来吗?

相关内容