前言
在做过各种语言的项目,对网站架构和职业要求有一个基础认知后,我认为要在卷翻天的职场立足,在了解并能使用前沿技术的同时还得打好计算机基础,所以痛下决心重拾大二摸鱼过去的OS实验。
2018年及以前MIT6.828是MIT的本科生OS课程,2019开始这门课被拆成了6.S081和6.828,分别成为本科生和研究生的OS课程。6.S081的实验由原来的5个拆成了10个,总体难度降低,更加易于基础并不牢固的学生学习。
我将记录2021年课程的实验全过程,下文是运行环境以及调试环境搭建的记录,着重记录如何使用CLion进行远程开发以及远程调试,这在网上很难找到相应资料。
非常佩服能使用原始gdb进行调试的人,已经是一个离不开ide的快速跳转,自动补全,集成调试的废物了。
课程链接:6.S081 / Fall 2021 (mit.edu)
什么是Xv6和RISC-V?
本课程用来教学和演示的操作系统是基于RISC-V指令集架构的Xv6操作系统,但不是一开始就如此。
本课程的前身6.828最开始使用的是Unix V6(简称V6,基于PDP-11硬件体系和旧式C语言开发)作为教学用OS,而在实验环节,学生们主要是在x86架构的CPU上实现一个称为Jos的“外核”架构(exokernel)的操作系统。
很多学生怀疑使用V6这样一个30多年前的,使用旧式C语言(比K&R C还要旧)开发的,并且在过时的PDP-11硬件上运行的系统是否合适。而且学生们还要苦于同时学习PDP-11和Intel x86两种不同架构的底层差别。于是在2006年夏天,课程的老师们决定以V6为基础,使用ANSI C写一个新的在Intel x86多处理器计算机上的系统,也就是Xv6,来代替V6。
从2019年开始,新课程6.S081使用精简指令集RISC-V替代了原有的复杂指令集x86来开发Xv6。
总的来说,RISC-V和x86都是CPU的指令集架构,Xv6和Windows、Linux、MacOS等都是运用这些指令集架构来管理硬件的操作系统。
安装Linux虚拟机以及必要工具下载
课程的文档里有各个平台的安装教程,本文以VMware Workstation Pro 16中安装Ubuntu20.04.4 Server作为基础环境。
环境配置指引:6.S081 / Fall 2021 (mit.edu)
安装虚拟机可以在百度上找到很多教程,这里不再赘述,仅放出下载链接
我下载的Ubuntu是Server版,只有命令行没有桌面,更喜爱桌面版可以自行下载。
安装完成并启动虚拟机后输入以下命令下载必要工具,主要是c/c++编译工具集,riscv64架构的gnu工具集,qemu虚拟机,git,适用于riscv64架构的gdb。
sudo apt-get install git build-essential gdb-multiarch qemu-system-misc gcc-riscv64-linux-gnu binutils-riscv64-linux-gnu
直接下载可能会过于缓慢,如果太慢了请先替换apt源为国内源(请尽量用较新的源)。这里使用的是阿里源和清华源,网上教程有很多,以下是我使用的源,用它替换掉*/etc/apt/source.list*中的内容后输入apt-get update
就行了。
#添加阿里源
deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
#添加清华源
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-backports main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-backports main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security main restricted universe multiverse
下载Xv6的git仓库
在用户文件夹下输入以下命令下载课程的Xv6源码,注意不要下载Xv6的官方源码而是下载课程改动过的源码,对改动内容感兴趣的话可以使用git log
查看改动内容。
git clone git://g.csail.mit.edu/xv6-labs-2021
下载速度可能很缓慢,可以直接从我的git仓库fork一份或直接clone。
我仓库my+实验名的分支是我自己完成后代码,ricsv分支是Xv6的源码,其他十个分支是对应lab的分支。
git clone git@github.com:Foliet/MIT-6.s081.git #ssh
git clone https://github.com/Foliet/MIT-6.s081.git #https
先进入文件夹内,然后输入以下两条命令。
git checkout util
make qemu
看到如下输出即为启动成功,一切顺利,否则按照课程原文说明逐个工具检查是否下载成功。
riscv64-unknown-elf-gcc -c -o kernel/entry.o kernel/entry.S
riscv64-unknown-elf-gcc -Wall -Werror -O -fno-omit-frame-pointer -ggdb -DSOL_UTIL -MD -mcmodel=medany -ffreestanding -fno-common -nostdlib -mno-relax -I. -fno-stack-protector -fno-pie -no-pie -c -o kernel/start.o kernel/start.c
...
riscv64-unknown-elf-ld -z max-page-size=4096 -N -e main -Ttext 0 -o user/_zombie user/zombie.o user/ulib.o user/usys.o user/printf.o user/umalloc.o
riscv64-unknown-elf-objdump -S user/_zombie > user/zombie.asm
riscv64-unknown-elf-objdump -t user/_zombie | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$/d' > user/zombie.sym
mkfs/mkfs fs.img README user/xargstest.sh user/_cat user/_echo user/_forktest user/_grep user/_init user/_kill user/_ln user/_ls user/_mkdir user/_rm user/_sh user/_stressfs user/_usertests user/_grind user/_wc user/_zombie
nmeta 46 (boot, super, log blocks 30 inode blocks 13, bitmap blocks 1) blocks 954 total 1000
balloc: first 591 blocks have been allocated
balloc: write bitmap block at sector 45
qemu-system-riscv64 -machine virt -bios none -kernel kernel/kernel -m 128M -smp 3 -nographic -drive file=fs.img,if=none,format=raw,id=x0 -device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0
xv6 kernel is booting
hart 2 starting
hart 1 starting
init: starting sh
$
配置Ubuntu的ssh服务器
输入sudo su
进入root用户模式,然后输入passwd
为root用户设置一个密码。
输入ls /etc/ssh
命令查看是否有sshd_config这个文件,如果没有则输入apt-get install openssh-server
下载。
将sshd_config
中的PermitRootLogin的#号去掉,并将值改为yes。
输入service ssh restart
重启ssh服务。(如果没设置开机自动启动,那么每次开机都要重启ssh服务)
完成后在物理机上打开一个shell,输入以下命令尝试连接虚拟机。
ssh root@{你的虚拟机ip}
ssh root@192.168.126.128 # 比如这样
如果不成功请转向百度找问题,搜索**“以root用户连接ssh服务器”**应该能找到很多教程。
在CLion上连接虚拟机
CLion是jetbrains公司面向c/c++的ide,通过学生优惠可以免费获取全家桶的一年通行证,并且在校期间可以无限续,只需要有edu后缀的邮箱就行了。
Clion下载地址:CLion:JetBrains 出品的 C 和 C++ 跨平台 IDE
学生优惠链接:Free Educational Licenses - Community Support (jetbrains.com)
配置工具链
新建一个项目,打开设置,选择构建、执行、部署,选择工具链,点上方加号➕添加一个远程主机,添加一个ssh凭据并手动输入gdb-multiarch的路径来替代默认gdb(原始gdb不能识别riscv的指令集)。
我这里是下了cmake,不下cmake也没关系,只需要管凭据和调试器。
配置部署服务器
点击上方工具,选择部署,点击配置,填好映射路径。
然后依次点工具、部署、浏览远程主机,就可以管理虚拟机的文件了,在这里可以很方便的直接管理虚拟机文件。
删除项目内初始的文件(如果有的话),右键项目文件夹,点击部署,然后下载虚拟机里的文件。
配置Makefile项目
打开设置,将构建目标设置为qemu-gdb。
*如果设置里显示未检测到Makefile项目就删掉项目文件夹里的.idea*文件夹,然后重新打开项目。**之前的设置会被初始化,需要重新设置一下。
设置完了之后打开Makefile文件,点右上角按钮重新加载项目。
此时索引就建立完毕了,可以自动补全和ctrl+B
来快速跳转了。
添加调试配置
在右上角打开运行/调试配置,添加一个远程调试的配置。
课程内的gdb服务器默认使用25000端口。
执行make
后会对内核程序和和每个用户程序各生成一个符号文件,内核的符号文件就叫kernel,用户程序的符号文件为_{程序名},例如ls的符号文件为*_ls*。
设置.gdbinit
在*/root文件夹下创建一个名为.gdbinit*的文件
向里面填入如下内容
set confirm off
set architecture riscv:rv64
file kernel/kernel
add-symbol-file user/_ls
set disassemble-next-line auto
set riscv use-compressed-breakpoints yes
这里是调试ls,如果要调试自己写的程序,比如说myproc,就添加一行add-symbol-file user/_myproc
。
启动调试服务器
在虚拟机的Xv6文件夹下输入make qemu-gdb
来启动gdb服务器,如遇到错误可以尝试make clean
来清除之前make生成的文件,shell输出以下内容即为开启成功。
*** Now run 'gdb' in another window.
qemu-system-riscv64 -machine virt -bios none -kernel kernel/kernel -m 128M -smp 3 -nographic -drive file=fs.img,if=none,format=raw,id=x0 -device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0 -S -gdb tcp::25000
如果显示25000端口已被占用或者文件fs.img被占用,应该是上一次运行没有正确退出,请自行百度查找如何根据占用端口或者文件获取pid,然后kill掉,这里建议使用lsof。
apt-get install lsof
安装lsof。lsof fs.img
和lsof -i:25000
查询进程。
开始调试
点击CLion右上角调试按钮开始调试ls程序,下方会显示连接成功,然后回到shell会发现可以输入命令了,此时我输入ls grep
,成功触发断点。
Xv6和CLion相关
- Xv6没有实现ps程序,要列出当前进程可以在Xv6的终端里中输入
ctrl+p
,关闭Xv6先按ctrl+a
再按x
。 - 调试Xv6时发生读取空指针,缓冲区溢出等错误时CLion不会报错,但是会导致调试异常,当系统中断,跳转到spinlock.c等文件内时需要格外注意。
- 在CLion内可以用
ctrl+alt+h
来查看一个函数被哪些函数调用了。