Home QEMU-x86 System emulator
Post
Cancel

QEMU-x86 System emulator

在x86机器上模拟x86,可以使用kvm加速。另外,x86环境中,硬件设备都相对标准(固定),参数设置可以相对简单。

Host环境

host环境为Ubuntu20.04 ,物理机。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="20.04.5 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.5 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

qemu 版本7.2.1,从默认配置编译而来

1
2
3
4
# ~/Downloads/qemu-7.2.1/build 
$ ./qemu-system-x86_64 --version
QEMU emulator version 7.2.1
Copyright (c) 2003-2022 Fabrice Bellard and the QEMU Project developers

下载系统组件

1
2
3
4
5
6
7
# download kernel
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.4.241.tar.xz
tar xvf linux-5.4.241.tar.xz

# download busybox
wget https://www.busybox.net/downloads/busybox-1.34.1.tar.bz2
tar xvf busybox-1.34.1.tar.bz2

编译内核

安装内核镜像编译依赖的相关工具,并使用默认配置编译内核,单独使用文件夹build_dir作为输出目录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 安装相关依赖工具
$ sudo apt install flex bison libncurses5-dev build-essential

# 进入linux source目录
$ cd linux-5.4.241

# 使用x86_64 默认配置文件 x86_64_defconfig 
$ ls arch/x86/configs/
i386_defconfig  tiny.config  x86_64_defconfig  xen.config


# 使用x86默认配置
$ make O=build_dir x86_64_defconfig

# 可以使用 make help 查看帮助
# 另外,可以 make menuconfig 进行一些内核配置和修改

# 使用多核编译,这里有20核
$ make O=build_dir bzImage -j20

initramfs

测试内核menuconfig中集成initramfs和单独制作initrd,qemu可以使用initrd(固定大小,要求内核支持使用的文件系统, 启动参数需要指定 /dev/ram0),但是测试initramfs未成功。

对做好的initramfs 的一些说明,添加或修改 initramfs 根目录下的 /init 文件,作为启动脚本,参考:

1
2
3
4
5
6
7
8
9
10
#!/bin/sh
  
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mdev -s

echo "hello ,this is my init script..."
/bin/sh

#  exec switch_root /mnt /sbin/init   # 切换真正的根文件系统,这里没有,需要有pid=1的进程调用

注意:/init 是最先执行的,先于 /etc/inittab/etc/init.d/rcS , 所以挂载 /proc/sys 需要写在 /init 中或者说应该先与 /bin/sh执行。这个和一般的根文件系统有些差别。另外,这里就运行到initramfs,不切换根文件系统。

另外,可以将这里最后的 /bin/sh替换为固定的程序,嵌入式环境中可以这么使用。

测试内核集成initramfs

qemu中使用单独的initramfs没有成功,但是将initramfs集成到内核中是可以的。

在内核的make meuconfig中,设置

1
2
3
General setup
    Initial RAM filesystem and RAM disk (initramfs/initrd) support
        Initramfs source file(s)

为做好的initramfs目录,然后编译 sudo make O=build_dir bzImage -j20,如果initramfs中有root权限的文件, 编译时可能会因为权限不足失败,所以这里加上sudo运行编译。

使用qemu模拟运行,因为内核中集成了initramfs,所以只需要一个内核即可。

1
2
3
4
5
6
7
8
sudo ./qemu-system-x86_64 \
    -machine pc \
    -nographic \
    -accel kvm \
    -smp 4 \
    -m 4096M \
    -kernel /my/path/to/linux-5.4.241/build_dir/arch/x86/boot/bzImage \
    -append "console=ttyS0 init=/init" 

使用 -machine help可以查看支持的设备。内核使用bzImage的文件,路径默认在build_dir/arch/x86/boot/bzImage, 启动参数中console=ttyS0,这个需要写,否则没有输出,init指定rootfs中的初始化程序或脚本。

这种方式主要的确定是initramfs和内核是集成在一起的,如果要单独修改其中之一,都需要重新编译。好处是qemu模拟时,不需要执行 initrd文件。

单独编译initrd

使用cpio工具将上述的rootfs打包,在qemu中使用initramfs的形式加载,启动失败,最后提示无法挂载跟文件系统,改用initrd 方式 试一下。该方式需要在内核配置中 File Systems中,将需要的文件系统编译进内核。一般initrd可以格式化为ext4,内核也是 默认将该文件系统编译进内核的。这样的话基本不需要修改。

内核需要的配置,一定要打开,将其编译进内核
ramdisk的大小和个数根据需要设置即可:

1
2
General setup > Initial RAM filesystem and RAM disk (initramfs/initrd) support
Device Drivers > Block devices > RAM block device support > (65536) Default RAM disk size (kbytes)

然后重新编译生成bzImage。

制作ramdisk
做好的rootfs目录为rootfs_my_init_ramfs。查看一下总大小:

1
2
$ du -sh ./rootfs_my_init_ramfs/
2.7M	./rootfs_my_init_ramfs/

然后制作,这里弄一个4MB大小的ramdisk就够了

1
2
3
4
5
6
7
dd if=/dev/zero of=myramdisk bs=1M count=4
mkfs.ext4 -F myramdisk
mkdir -p mnt_for_loop
sudo mount -t ext4 myramdisk ./mnt_for_loop/  -o loop
sudo cp -arf rootfs_my_init_ramfs/*  mnt_for_loop/
sudo umount mnt_for_loop
gzip -9 ./myramdisk 

使用qemu可以成功启动

1
2
3
4
5
6
7
8
9
sudo ./qemu-system-x86_64 \
    -machine pc \
    -nographic \
    -accel kvm \
    -smp 4 \
    -m 4096M \
    -kernel /home/pjw/Downloads/linux-5.4.241/build_dir/arch/x86/boot/bzImage \
    -append "root=/dev/ram0 rw rootfstype=ext4 console=ttyS0 init=/linuxrc" \
    -initrd /home/pjw/Downloads/busybox-1.34.1/myramdisk.gz 

这里主要是加上了init ramdisk文件,并且修改了内核启动参数。

其他补充

x86在qemu中的模拟使用,更多的情况是类似于虚拟机的。qemu可以建立虚拟磁盘,给guest os使用, 另外还有网卡配置,图形界面配置,usb,cdrom,甚至快照功能等,和vmware虚拟机软件相似。

参考

qemu学习笔记2之搭建x86虚拟机

QEMU搭建X86_64 + Ubuntu虚拟系统环境

This post is licensed under CC BY 4.0 by the author.