因为学校的操作系统课程设计要用这玩意,所以就要配置这个玩意
配置这玩意相对还是快的,但我也走了点弯路
如果图方便的话我还是建议用Docker方式安装
我的环境是WSL的Debian
我也会在github上更新我的实现代码
之前参考的任务说明是北大的pintos文档
但是学校给的代码是CS162最新的代码,里面代码结构变化很大
我决定还是保留之前写的lab1和lab2,但后面就只写学校的版本了
PKU-Docker
Berkeley-Docker
<0x00> 前置
需要配置WSL,然后安装Debian
目前的Debian版本是12
如果后面的版本遇到些gcc编译器问题的话就换老版本的Ubuntu LTS版本吧
然后需要git和稳定的维图诺·普莱维特·奈特沃克
<0x01> 拉取pintos仓库
git clone git://pintos-os.org/pintos-anon --depth=1
需要提前配置下git的proxy,不然可能会很慢
如果是ZJUT学生,做课设的话老师会给一个学校自己的gitlab链接
用那个链接克隆一个仓库即可
(其实克隆CS162的也可以,貌似链接年年换,这里就不贴了,Github一搜就有)
<0x02> 配置Debian需要的软件包
# 编译环境
sudo apt install make build-essential
# qemu模拟器
sudo apt install qemu
# 安装调试器
sudo apt install gdb
慢的话就换下apt的源
<0x03> 简单配置
修改./threads/Make.vars中的SIMULATOR
SIMULATOR = --qemu
然后修改下./utils/pintos
# 104行左右
$sim = "qemu" if !defined $sim;
20年之后的linux貌似不会提供stropts.h这个头文件
但我们直接系统里创建一个空的就可以了(注释掉也行)
sudo nano /usr/include/stropts.h
随便输入点注释的东西然后保存就可以
再注释./utils/squish-pty.c中下面的代码
// 大概在288行
if (isastream (slave))
{
if (ioctl (slave, I_PUSH, "ptem") < 0
|| ioctl (slave, I_PUSH, "ldterm") < 0)
fail_io ("ioctl");
}
这样就可以了
(我不是很喜欢动path这种东西,网上说的其他修改貌似也都不是很关键)
<0x04> 尝试运行
在工作路径./src下面一条条执行
# 编译utils的文件
cd ./utils
make
# 回到./src
cd ..
# 编译内核
cd ./threads
make
# 进入编译好的内核文件夹
cd ./build
# 通过提供的脚本运行pintos
../../utils/pintos -- run alarm-multiple
理论上pintos就会运行了
<0x05> 在vscode中调试
这部分参考了这个仓库的配置文件
原本这个东西教程是在命令行用gdb调试
能调试但不方便
而vscode的C/C++插件的调试功能就是靠gdb实现的
我们能不能让vscode调用gdb连接到pintos进行调试呢?
答案是可以的,只是需要亿点配置
vscode连接wsl
这个在用vscode连接wsl的时候会跳提示,要求安装wsl的插件
安装就可以了
安装完会多很多插件,这是对的
点击左下角的图标,选择connect to WSL
然后vscode就会自己配置远程环境,只要WSL网络正常
安装C/C++插件
跟平时不同的是,我们需要给WSL安装C/C++插件,不过这很简单
前面跟往常一样,先是搜索C++,然后安装插件
不同的是安装后,会提示要不要在远程WSL那边安装,安装就可以了
然后vscode就会自己装了,等就可以了
(vscode全自动)
tasks.json和launch.json
这俩是什么
如果是经常用vscode写C++的用户,多少对这玩意有点印象
这两个东西算是调试控制脚本和编译控制脚本
tasks控制怎么启动应用,launch控制怎么启动调试程序
这两个东西一般是在./.vscode文件夹里面的
直接创建就好,vscode会自己识别的
如果理解的话可以跳过这部分直接从附录找写好的文件
配置tasks.json
创建tasks.json,然后输入这些东西
{
"version": "2.0.0",
"tasks": [
{
"label": "[Lab1] compile",
"type": "shell",
"command": "make",
"options": {
"cwd": "${workspaceFolder}/threads"
}
},
{
"label": "[Lab1] Run In GDB Mode",
"type": "shell",
"isBackground": true,
"problemMatcher": [
{
"pattern": [
{
"regexp": ".",
"file": 1,
"location": 2,
"message": 3
}
],
"background": {
"activeOnStart": true,
"beginsPattern": ".",
"endsPattern": ".",
}
}
],
"dependsOn": [
"[P1] compile"
],
"command": "../../utils/pintos -v -k --gdb -- run ${input:test_name}",
"options": {
"cwd": "${workspaceFolder}/threads/build"
}
}
],
"inputs": [
{
"id": "test_name",
"type": "promptString",
"description": "Name of the Test to Debug"
}
]
}
这里创建了两个task,一个负责编译,一个复制运行
如果是自己配置的话注意路径
配置launch.json
创建launch.json,输入下面的东西
{
"version": "0.2.0",
"configurations": [
{
"name": "[Lab1] Debug",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/threads/build/kernel.o",
"miDebuggerServerAddress": "127.0.0.1:1234",
"preLaunchTask": "[P1] Run Test in GDB mode",
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"text": "-enable-pretty-printing",
"description": "Enable pretty-printing for gdb",
"ignoreFailures": true
},
{
"text": "source -v ${workspaceFolder}/misc/gdb-macros",
"description": "Import Pintos GDB macros file",
"ignoreFailures": false
}
],
"symbolLoadInfo": {
"loadAll": true,
"exceptionList": ""
}
}
]
}
记得注意路径
尝试运行
首先在./thread/init.c里面找到main,打个断点,然后运行
理论上这时候运行会让你选配置文件,选我们创建的debug配置
这时候就像运行别的C++项目一样,开始debug,体验好多了
需要注意的是,上面的配置仅针对lab1,后面的可能需要单独配置
(后面的我还没开始写)
<0x06> 配置Test
因为没把pintos配置到path中,所以在./thread/build下执行make test会找不到pintos
有把pintos添加到path中就不用动这些东西
这时候就要修改./test下面的Make.tests文件
# 大概在55行
TESTCMD = ../../utils/pintos -v -k -T $(TIMEOUT)
TESTCMD += $(SIMULATOR)
TESTCMD += $(PINTOSOPTS)
这样就可以了
警钟长鸣:不要用Arch编译
如果使用Arch编译这个东西的话可能会遇到loader.bin的大小有128M
而不是正常的512字节
不只是WSL中Arch会出现这个问题,物理机Manjaro也会这样
具体原因不是很清楚,我怀疑是gcc版本问题
我测试过Ubuntu22的gcc11和Debian12的gcc12,这两个都可以成功编译
但Arch的是gcc14,可能较高的gcc版本导致编译行为不符合预期
不过我暂时还没尝试在Arch中使用gcc11编译过
(源码编译gcc时间太长了,就摸了)