诸君共勉
目录
简介
操作系统实践课程实践任务,包括开发环境的准备与交叉编译器、qemu模拟器、gdb调试器等工具的安装与使用。
基于qemu的RISC-V 64 位版本的 Linux的启动。
报告截图的用户名会有变化,因为我创建了多台虚拟机进行实验。
环境准备
- VMware Workstation 16 Pro
- 操作系统:ubuntu-20.04.6-desktop-amd64
虚拟机搭建见个人总结博文:搭建虚拟机
直接使用官方提供的 GNU工具链和 QEMU 模拟器,执行如下命令在线安装:
sudo apt update
sudo apt install build-essential gcc make perl dkms git gcc-riscv64-unknown-elf gdb-multiarch qemu-system-misc
至此环境准备结束。
交叉编译器
尝试过程
GNU交叉编译工具链已安装 riscv64-unknown-elf-gcc
。
riscv64-unknown-elf-gcc --version
尝试编使用riscv64-unknown-elf-gcc
进行编译,报错。
由参考资料errata.pdf
【勘误4-2】可知,错误是正常且不影响课程的。
尝试使用riscv64-linux-gnu-gcc
成功编译。
但是qemu模拟运行却报错。
Invalid ELF image for this architecture
使用file查看文件
发现默认是Shared object file,在编译的时候加上-no-pie
参数。
riscv64-linux-gnu-gcc -no-pie hello.c
重新file查看。
但是重新qemu运行依然报错,思考后认为是编译默认64位(riscv64-unknown-elf-gcc的参数指定在riscv64-linux-gnu-gcc中无效)和qemu模拟32位的冲突。
成功实现
参照参考文献【5】,重新进行。
编译后file查看确定无误为RISC-V,交叉编译成功。
qemu模拟器进行模拟,报错按照提示修复即可。
可以看到这个目标文件是不能在当前的系统下运行的
最后通过qemu模拟运行,成功!
qemu模拟器
QEMU 是一套由 (Fabrice Bellard) 编写的以 GPL 许可证分发源码的计算机系统模拟软件,在 GNU/Linux 平台上使用广泛。
在环境准备中已经安装好了qemu,下面检查一下是否成功。
使用如下命令查看qemu:
qemu-system-riscv64 --version
gdb调试器
在环境准备中已经安装好了gdb,下面检查一下是否成功。
make构造工具
自动化构建管理工具。
上下文切换代码示例运行
os.h
的context结构体存储寄存器状态。
我们的系统仅仅运行在一个核中,要实现多任务需要保存上下文的值(实际上就是寄存器以及程序计数器等重要环境的值)。
关键函数是(switch_to)
启动RVOS
工作目录是riscv64-linux
,交叉工具链目录是riscv-gnu-toolchain
。
制作交叉工具链
根据参考文献【5】,以及前文的内容完成交叉工具链的制作。
需要注意参考文献【6】中的所有内容都需要把
riscv64-unknown-linux-gnu-gcc
替换为$WS/install/bin/riscv64-unknown-linux-gnu-gcc
在学习过程中发现就算是按照指导进行使用国内镜像也总是会有问题,在解决的过程中找到了前辈分享的资源riscv-gnu-toolchain,可以免去苦苦等待且可能出问题的子仓库下载内容。
下载源码
下载源码压缩包并解压。
wget https://download.qemu.org/qemu-5.1.0.tar.xz
tar xvJf qemu-5.1.0.tar.xz
编译并安装。
cd qemu-5.1.0/
./configure --target-list=riscv64-softmmu,riscv64-linux-user --prefix=/opt/qemu
make -j $(nproc)
sudo make install
导出 qemu 的安装目录并验证安装是否正确。
制作内核
回到工作目录riscv64-linux,然后下载内核源码并进入linux目录。
检出到5.4版本。
编译和配置。
make ARCH=riscv CROSS_COMPILE=$WS/install/bin/riscv64-unknown-linux-gnu- defconfig
make ARCH=riscv CROSS_COMPILE=$WS/install/bin/riscv64-unknown-linux-gnu- -j $(nproc)
再次强调这里不是
riscv64-unknown-linux-gnu
,而是$WS/install/bin/riscv64-unknown-linux-gnu-
后面也一样。
制作 rootfs
下载并进入busybox。
git clone https://gitee.com/mirrors/busyboxsource.git
cd busyboxsource/
配置busybox。
CROSS_COMPILE=$WS/install/bin/riscv64-unknown-linux-gnu- make menuconfig
这里遇到bug如下:
fatal error: curses.h: No such file or directory
通过如下命令解决:
sudo apt-get install libncurses5-dev
继续运行
注意这里要把终端窗口大小调大一些,不然会报如下错误:
是我窗口太小不能展示出busybox的GUI界面所致,调大窗口即可。
成功运行。
设置打开配置菜单后进入第一行的 “Settings”,在"Build Options"节中,选中 “Build static binary (no shared libs)”,设置好后退出保存配置。
编译和安装。
CROSS_COMPILE=$WS/install/bin/riscv64-unknown-linux-gnu- make -j $(nproc)
CROSS_COMPILE=$WS/install/bin/riscv64-unknown-linux-gnu- make install
可以看到_install目录下生成的内容。
制作一个最小的文件系统。
返回工作目录,输入以下命令。
qemu-img create rootfs.img 1g
mkfs.ext4 rootfs.img
接下来输入如下命令,将_install内的内容拷贝,创建一些文件。
mkdir rootfs
sudo mount -o loop rootfs.img rootfs
cd rootfs
sudo cp -r ../busyboxsource/_install/* .
sudo mkdir proc sys dev etc etc/init.d
然后另外再新建一个最简单的 init 的 RC 文件,具体步骤如下:
cd etc/init.d/
sudo touch rcS
sudo vi rcS
将以下内容粘入文件
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
/sbin/mdev -s
然后修改 rcS 文件权限,加上可执行权限,这样当 busybox 的init 运行起来后,就能运行这个 /etc/init.d/rcS 脚本。
sudo chmod +x rcS
最后退出 rootfs 目录并卸载文件系统:
sudo umount rootfs
至此,文件系统就制作完成了。
运行
准备工作全部完成,退回工作目录。
运行如下代码:
qemu-system-riscv64 -M virt -m 256M -nographic -kernel linux/arch/riscv/boot/Image -drive file=rootfs.img,format=raw,id=hd0 -device virtio-blk-device,drive=hd0 -append "root=/dev/vda rw console=ttyS0"
出现问题。
根据参考文献【6】
修改参数如下:
qemu-system-riscv64 -M virt -m 256M -nographic -kernel linux/arch/riscv/boot/Image -drive file=rootfs.img,format=raw,id=hd0 -device virtio-blk-device,drive=hd0 -append "root=/dev/vda rw console=ttyS0" -bios default
成功运行!
参考文献
[1] 课程视频讲解
[2] riscv-operating-system-mooc
[3] csdn [MIT 6.S081] Lab 0: 实验配置, 调试及测试
[4] Running 64- and 32-bit RISC-V Linux on QEMU
[5] 制作交叉工具链 riscv-gnu-toolchain
[6] target-riscv
[7] 在 QEMU 上运行 RISC-V 64 位版本的 Linux