Linux

無法讓busybox switch_root 工作

  • October 10, 2019

我正在開發一個使用 initramfs 啟動的嵌入式 ARM Linux 系統。(如果您有興趣,這裡有一些早期 問題的背景。)到目前為止,部分感謝這裡收到的幫助,我可以通過 TFTP 使用嵌入式 initramfs 引導核心。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 選項但沒有成功。

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_root您的 initramfs 初始化腳本中的命令應該switch_root使用exec. IE

exec switch_root ...

“未找到”錯誤的另一個問題可能是因為找不到執行檔所需的共享庫,因為 initramfs 根文件系統沒有它們。如果您可以switch_root使用exec,那麼“未找到”錯誤可能會消失。

引用自:https://unix.stackexchange.com/questions/5032