qemu运行linux内核

qemu运行linux内核

准备内核

由于实体机是linux,我直接使用/boot目录下vmlinuz-5.4.0-81-generic现有的内核,当然下载内核源码进行编译也是可以的

创建文件系统

内核启动之后需要加载文件系统来启动init进程,所以需要实现准备文件系统和init进程,首先先创建文件系统

1 创建虚拟机磁盘

1
qemu-img create -f raw disk.raw 512M

2 格式化文件系统

1
mkfs -t ext4 ./disk.raw

此时使用以下命令

1
qemu-system-x86_64 -m 512M -kernel vmlinuz-5.4.0-81-generic -drive format=raw,file=./dist.raw -append "root=/dev/sda"

会提示init文件未找到

创建init进程

1 挂载文件系统

1
2
mkdir img
mount -o loop ./disk.raw ./img

2 init进程

init进程是系统第一个启动的进程,实际上只要是一个linux里的可执行文件就行,比如hello world

1
2
3
4
5
6
7
8
9
/* main.c */
#include <stdio.h>

void main()
{
printf("Hello World\n");
fflush(stdout);
while (1);
}

编译后复制到img目录

1
2
gcc -static -o main main.c
cp main img
1
qemu-system-x86_64 -m 512M -kernel vmlinuz-5.4.0-81-generic -drive format=raw,file=./disk.raw -append "root=/dev/sda init=/main"

运行后屏幕会有输出hello world

3 busybox

使用以上程序作为init进程并没有实际意义,实际的init需要完成启动后拉起其他进程的功能,例如systemv,busybox等。这里选择busybox作为init进程,主要是由于busybox自身带了shell及相关工具便于使用

1 下载busybox源码,这里使用的版本是1.29.2

2 进入目录编译

1
2
3
make defconfig
make menuconfig #需要选择编译静态库
make

3 安装

1
make CONFIG_PREFIX=../img install

CONFIG_PREFIX选择上面挂载的目录

启动内核

1
qemu-system-x86_64 -m 512M -smp 2 -kernel vmlinuz-5.4.0-81-generic -drive format=raw,file=./disk.raw -append "init=/linuxrc root=/dev/sda" 

能够正常启动后可以看到屏幕上有一些错误提示,需要调整一下配置文件

busybox配置

1 创建配置文件

1
2
3
4
5
6
mkdir ./img/proc
mkdir ./img/sys
mkdir ./img/dev
mkdir -p ./img/etc/init.d
touce ./img/etc/init.d/rcS
chmod u+x ./img/etc/init.d/rcS

2 修改配置文件rcS

1
2
3
4
5
#!/bin/sh
mount -t proc proc /proc
mount -t sysfs sysfs /sys
# 文件系统无法修改运行以下命令
# mount -o remount,rw /

之后重新启动内核后正常