Skip to content

# 虚拟机中以pid1运行

## 概述

本教程基于`openEuler LTS 22.03`版本进行实践，理论上适用于其他`Linux`发行版本。首先通过`dracut`命令制作剔除了`systemd`的`initramfs`镜像，然后基于该镜像添加新的`grub`启动条目，并在该启动条目中以`sysmaster-init`作为一号进程实现虚拟机环境的启动初始化。

## 部署和使用

### `initramfs`镜像制作

1. 为了避免`initrd`阶段`systemd`的影响，需要制作一个剔除`systemd`的`initramfs`镜像，并以该镜像进入`initrd`流程。使用如下命令：

    # dracut -f --omit "systemd systemd-initrd systemd-networkd dracut-systemd" /boot/initrd_withoutsd.img

1. 得到上述`initramfs`后，在`grub.cfg`中增加新的启动项，`aarch64`下的路径为`/boot/efi/EFI/openEuler/grub.cfg`，`x86_64`下的路径为`/boot/grub2/grub.cfg`：

    ...
    ### BEGIN /etc/grub.d/10_linux ###
    menuentry 'openEuler (5.10.0-60.18.0.50.oe2203.aarch64) 22.03 LTS' --class openeuler --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-5.10.0-60.18.0.50.oe2203.aarch64-advanced-53b0b401-a14c-43f1-9d96-9a66143bbb17' {
            load_video
            set gfxpayload=keep
            insmod gzio
            insmod part_gpt
            insmod ext2
            set root='hd0,gpt2'
            if [ x$feature_platform_search_hint = xy ]; then
              search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2  2a438da5-a305-4682-a45f-5cee6f02c3c6
            else
              search --no-floppy --fs-uuid --set=root 2a438da5-a305-4682-a45f-5cee6f02c3c6
            fi
            echo    'Loading Linux 5.10.0-60.18.0.50.oe2203.aarch64 ...'
            linux   /vmlinuz-5.10.0-60.18.0.50.oe2203.aarch64 root=/dev/mapper/openeuler-root ro rd.lvm.lv=openeuler/root rd.lvm.lv=openeuler/swap video=VGA-1:640x480-32@60me console=tty0 crashkernel=1024M,high smmu.bypassdev=0x1000:0x17 smmu.bypassdev=0x1000:0x15 video=efifb:off
            echo    'Loading initial ramdisk ...'
            initrd  /initramfs-5.10.0-60.18.0.50.oe2203.aarch64.img
    }
    ### 新增如下启动项 ###
    menuentry 'Boot with sysmaster' --class openeuler --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-5.10.0-60.18.0.50.oe2203.aarch64-advanced-53b0b401-a14c-43f1-9d96-9a66143bbb17' {
            load_video
            set gfxpayload=keep
            insmod gzio
            insmod part_gpt
            insmod ext2
            set root='hd0,gpt2'
            if [ x$feature_platform_search_hint = xy ]; then
              search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2  2a438da5-a305-4682-a45f-5cee6f02c3c6
            else
              search --no-floppy --fs-uuid --set=root 2a438da5-a305-4682-a45f-5cee6f02c3c6
            fi
            echo    'Loading Linux 5.10.0-60.18.0.50.oe2203.aarch64 ...'
            linux   /vmlinuz-5.10.0-60.18.0.50.oe2203.aarch64 root=/dev/mapper/openeuler-root rw rd.lvm.lv=openeuler/root rd.lvm.lv=openeuler/swap video=VGA-1:640x480-32@60me console=tty0 crashkernel=1024M,high smmu.bypassdev=0x1000:0x17 smmu.bypassdev=0x1000:0x15 video=efifb:off init=/init
            echo    'Loading initial ramdisk ...'
            initrd  /initrd_withoutsd.img
    }
    ...

1. 增加启动项时，拷贝一份原有启动项，并做以下四处修改：

2. 新增启动项需要避免和原启动项重名，例如上述案例中设置为`Boot with sysmaster`：

    menuentry 'Boot with sysmaster'

- 内核启动参数需要修改`root=/dev/mapper/openeuler-root ro`为`root=/dev/mapper/openeuler-root rw`。因为目前`sysmaster`并未实现在切根后重新挂载根分区的功能，所以小系统中的根分区需要挂载成`rw`。

- 启动参数中需要显示指定一号进程`init=/init`，在安装脚本`install_sysmaster.sh`中，我们会生成`/init`软链接指向`sysmaster-init`，从而避免内核以`systemd`作为1号进程启动。

- `initrd`项需要对应修改为`initrd /initrd_withoutsd.img`，此`img`为步骤1生成。

### 安装`sysmaster`

1. 构建`sysmaster`的`debug`或`release`二进制版本：

    # cargo build --all [--release]

1. 在源码根目录下使用安装脚本`install_sysmaster.sh`将`sysmaster`的二进制文件、系统服务、配置文件等安装到系统中，执行以下命令：

    # sh -x tools/run_with_vm/install_sysmaster.sh [debug|release]

可以指定安装`debug`或`release`版本，未指定时默认安装`debug`二进制版本。

1. 启动串口登陆服务：

根据体系结构启动对应的串口登陆服务，`aarch64`对应`serial-getty-ttyAMA0.service`，`x86_64`对应`serial-getty-ttyS0.service`。此服务主要针对有`console`串口的情况，例如`virsh console`进入串口，私人笔记本创建的虚拟机，默认应该都是只有`tty1`。

开机启动后手动执行`sctl start`命令启动串口登陆服务，或者将该服务添加到`multi-user.target`配置的`Requires`字段中实现开机自启。

    # sctl start <serial-getty-ttyAMA0.service|serial-getty-ttyS0.service>

### 系统启动

虚拟机重启，在`grub`引导启动界面选择对应的启动项。启动后，可以通过`tty1`或者`ssh`登陆。

## 卸载`sysmaster`

执行以下命令，可以从系统中卸载`sysmaster`：

    # rm -rf /lib/sysmaster
    # rm -rf /etc/sysmaster
    # unlink /init

Last update: September 21, 2023
Created: April 20, 2023