前情
基于手上没有板子,想想试试 qemu 的模拟功能,这里可能并不会有一个流程化的过程,这方面的技术步骤网上还是有很多资源的,没必要再写了,主要是把自己的一些问题,主要的内容有个记录
记录
安装 qemu
ubuntu 系统 下用 apt install qemu-xx ,tab 键就可以发现应该安装什么,安装后命令行会有 qemu-
开头的命令,qemu-ARCH
是模拟软件运行的,qemu-system-ARCH
是模拟系统运行的,这里主要用 qemu-system-arm, qemu-system-aarch64
,其中 arm
是对32bit 的模拟,aarch64
是对 64bit 的模拟。
编译器
arm
的编译器可以直接下载,用 apt install gcc-arm-linux-gnueabi gcc-arm-none-eabi
其中前面一个是用于编译 linux 相关系统的,后一个主要用于编译祼机系统。 如果需要 g++
也是一样的安装,只是只有 arm-linux-gnueabi
版本
编译 busybox
- 要编译
static
版本 - 我没有测试 32bit 版本,选择 64bit 版本,在编译过程中遇到了 32bit 编译失败的问题,现象已经不在了,当时应该是编译器版本低的原因,然后就使用 64bit 的
- 编译命令
make -j 4 ARCH=arm64 CROSS_COMPILE=arm-linux-gnueabi-
- 编译完安装默认是在当前目录的
_install
目录下
制作最小文件系统
- 基于
_install
目录,创建dev, etc/init.d
目录 -
dev
下面创建mknod console c 5 1
,mknod null c 1 3
- 还有几个要准备的文件是
etc/inittab
,etc/init.d/rcS
,etc/fstab
,文件内容参见 文后列表
编译内核
- 下载内核源码
-
make defconfig
,arm64
只有这个选项可以用,不像arm
里面有很多,当前可以执行后再自己配置 -
General Setup --> Initial RAM filesytem and RAM disk -> (_install) Initramfs source file(s)
这个要记得加上 busybox 生成的目录位置 -
make ARCH=arm64 CROSS_COMPILE=arm-linux-gnueabi-
不是最小内核,编译时间有点长 - 我当时加上
-j4
编译的时候会有错,也没有去找原因,可能并发编译哪里的依赖没控制 好吧
运行
- qemu 运行的命令
qemu-system-aarch64 -machine virt -cpu cortex-a57 -m 2048 -smp 2 -kernel Image -machine type=virt --nographic --append "rdinit=linuxrc console=ttypAMA0"
,运行过程中,我的出现kernel panic
什么init=
这个没有指定,最后测试将_install
目录下的linuxrc
更名为init
即可,具体原因还没到内核源码中去查找 - 其中
--nographic
是为了输出 ,也可以换成-serial stdio
,这样为多开一个窗口,将窗口关闭就可以关闭运行中的系统,否则出现 kernel panic 的现象就只能能过 kill 来关闭,麻烦。
用独立文件系统
- 如果使用上面的方法,文件系统有更新需要重新编译内核,于是换一种方法,把文件系统独立出来
- 制作文件系统镜像,最简单的方法
-
dd if=/dev/zero of=rootfs.img bs=1M count=512
我为了把内核模块都放进去,做的比较大一些 -
mkfs.ext4 rootfs.img
格式化 -
mount rootfs.img b
挂载后,将_install
下的内容都放到b
目录下 - 使用命令
qemu-system-aarch64 -machine virt -cpu cortex-a57 -m 2048 -smp 2 -kernel Image -machine type=virt --nographic --append "root=/dev/vda rw console=ttypAMA0" -hda rootfs.img
来运行 - 其中
/dev/vda
可能 会不一样,我一开始用的sda
根据内核的错误提示,发现加载后是vda
于是用了这个 - 当有问题时可以用
gdb
来debug
内核 - 运行
arm-xxxgdb Image
之后在提示符下输入target remote localhost:1234
就可以开始调试,具体还没怎么用,就不说了,记得qemu
命令要加-s -S
使能调试功能 - 用这种模式时,在
_install
目录下要先建好/proc, /tmp /sys
目录,写在脚本中没有效果 - 当然
gdb
要安装 ,跟安装 gcc 差不多
测试 u-boot
- 下载 u-boot 编译
- 整个过程跟内核 差不多
- 我在编译好之后,
qemu-system-aarch64 -M virt -kernel u-boot -serial stdio
来运行,出现了没有打印,用gdb
调试,调试也看不出什么,再关闭后发现u-boot
的打印了,具体的以后再研究。 - 之后 u-boot 编译为 raspberry 版本之后,一直没有提示,调试之后也没有,具体原因还在看,就不说了
文件参考
部分文件内容来自 《奔跑吧,Linux 内核》
etc/init.d/rcS
mkdir -p /proc
mkdir -p /tmp
mkdir -p /sys
mkdir -p /mnt
/bin/mount -a
mkdir -p /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
etc/inittab
::sysinit:/etc/init.d/rcS
::respawn:-/bin/sh
::askfirst:-/bin/sh
::ctrlaltdel:/bin/umount -a -r
etc/fstab
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
debugfs /sys/kernel/debug debugfs defaults