在 Linux 用户模式下退出 init 的正确方法

ven*_*uil 2 c linux init linux-kernel user-mode-linux

我使用自定义 initrd 在用户模式下编译了 Linux 内核 5.6,使用以下方法创建:

mkdir initrd
cd initrd
mkdir bin dev etc home mnt proc sys usr
mknod dev/console c 5 1
Run Code Online (Sandbox Code Playgroud)

initrd/init.c初始化文件

#include <stdio.h>
#include <stdlib.h>
#include <sys/mount.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    printf("init\n");

    mount("none", "/proc", "proc", MS_MGC_VAL, "");
    mount("none", "/sys", "sysfs", MS_MGC_VAL, "");
    mount("none", "/dev", "devtmpfs", MS_MGC_VAL, "");

    if (access("/dev/ubda", F_OK) != -1) {
        printf("/dev/ubda exists\n");
    } else {
        printf("/dev/ubda not exists\n");
    }

    return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

该程序检查通过ubd0=...选项传递的磁盘。

gcc -static -o init init.c.

毕竟我编译了内核

make mrproper
make mrproper ARCH=um
make defconfig ARCH=um
make menuconfig ARCH=um
make linux ARCH=um
Run Code Online (Sandbox Code Playgroud)

我更改了.config文件中的以下选项(使用 menuconfig)

CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE="initrd"
CONFIG_RD_GZIP=y
CONFIG_RD_BZIP2=y
CONFIG_RD_LZMA=y
CONFIG_RD_XZ=y
CONFIG_RD_LZO=y
CONFIG_RD_LZ4=y
Run Code Online (Sandbox Code Playgroud)

毕竟我试图运行./linux mem=32M,除了退出之外,一切看起来都很好

mkdir initrd
cd initrd
mkdir bin dev etc home mnt proc sys usr
mknod dev/console c 5 1
Run Code Online (Sandbox Code Playgroud)

我怎样才能正确退出?

S.M*_*.M. 5

init 进程绝不能退出。退出 init 的正确方法是关闭。

#include <linux/reboot.h>

int main(int argc, char *argv[]) {
  // ...
  // return EXIT_SUCCESS;

  sync();
  reboot(LINUX_REBOOT_MAGIC1, 
     LINUX_REBOOT_MAGIC2, 
     LINUX_REBOOT_CMD_POWER_OFF, 0);
}
Run Code Online (Sandbox Code Playgroud)

在 glibc 和大多数替代 libc(包括 uclibc、dietlibc、musl 和其他一些)下,一些涉及的常量已获得符号名称 RB_*,并且库调用是系统调用的 1 参数包装器:

#include <sys/reboot.h>

int main(int argc, char *argv[]) {
  // ...
  // return EXIT_SUCCESS;

  sync();
  reboot(RB_POWER_OFF);
}
Run Code Online (Sandbox Code Playgroud)

对于停止或重启系统的 cmd 值,调用成功reboot()不会返回。