CS130 操作系统I Project 0 准备工作
Project: 基于PintOS的手搓操作系统!
整个学期的Project分为5个部分:
- Project 0: 准备工作
- Project 1: Threads | 进程
- Project 2: User Programs | 用户程序
- Project 3: Virtual Memory | 虚拟内存
- Project 4: File Systems | 文件系统
每个部分基于前一个部分的工作完成,所以还请务必按照顺序!
学期内的Project是在学校的在线平台上完成,那里已经搭好了VM的环境,需要ssh远程过去写代码、跑调试。但是在假期内学校在线端口无法访问,Project需要通过在本地手动配置环境并部署来完成。接下来介绍的所有过程都基于本地Windows 11系统,从头开始配置环境、部署Project。
Project 0: 准备工作
安装与调试
由于我是Windows 11用户,之前听说在Windows上不能安装Docker,但是发现了Docker Desktop过后,Windows上也能轻松使用Docker了。虽然说本质上还是一种WSL(Windows Subsystem for Linux),但是省得我装一个VMWare或者直接在本机上装一个Ubuntu(事实上我都装了,希望后来者可以不用走这条弯路)。具体步骤如下:
安装Docker
从官网链接下载,非苹果机的Windows用户选择 Download for Windows - AMD64,下载后按照提示正常安装即可;安装完成后打开,可能会出现要求安装WSL的命令行窗口,按任意键安装,大约需要3-5min完成;
下载PintOS源代码包
有两种方法:①按照学校提供的链接下载并解压(需要校内VPN访问),或者②从北大的Github仓库下拉:
1 | git clone git@github.com:PKU-OS/pintos.git |
在本地进行系统测试
打开Decker Desktop客户端,打开系统的命令行窗口,完成如下对话:
将以下输入路径调整成实际安装路径后输入:
1
docker run -it --rm --name pintos --mount type=bind,source=absolute/path/to/pintos/on/your/host/machine,target=/home/PKUOS/pintos pkuflyingpig/pintos bash
然后命令行应该会变成如下格式(具体内容可能不同):
ps. 如果提示
fail to connect to the docker API,可以尝试挂梯子使用(先打开Decker Desktop)1
root@9113da5c984f:~#
这说明一个微型的Ubuntu系统正在你的电脑上运行!
接下来键入:
1
pwd
会有如下回话:
1
/home/PKUOS
接下来键入:
1
ls
会有如下回话:
1
pintos toolchain
以上对话如果均正常,那么接下来可以尝试启动系统了,键入:
1
2
3
4
5cd pintos/src/threads/
make
cd build
pintos --如果回话的最后几行类似于:
1
2
3
4
5
6
7
8Pintos hda1
Loading............
Kernel command line:
Pintos booting with 3,968 kB RAM...
367 pages available in kernel pool.
367 pages available in user pool.
Calibrating timer... 32,716,800 loops/s.
Boot complete.那就说明你的PintOS系统在本地成功运行了!
注:此时可以按
Ctrl + C关闭PintOS系统,然后按Ctrl + D退出微型的Ubuntu系统。目前已经完成的架构,是在Windows上通过WSL和Docker建立了一个Ubuntu容器(Container),然后在这个Ubuntu容器内部通过QEMU模拟了一台x86计算机的硬件结构,然后在这台模拟的计算机上运行了PintOS系统,这个结构画出来就是这样的:
1
2
3
4
5
6Host OS(Windows / macOS / Linux)
└── Docker
└── Ubuntu Linux(容器里的用户态 Linux)
└── QEMU(一个普通用户程序)
└── 模拟的 32-bit x86 计算机(CPU, 内存, 磁盘等硬件)
└── PintOS(操作系统)
在本地进行程序测试
尝试运行Project 1的本地test:
打开任意终端,启动Ubuntu系统:
1
docker run -it --rm --name pintos --mount type=bind,source=absolute/path/to/pintos/on/your/host/machine,target=/home/PKUOS/pintos pkuflyingpig/pintos bash
1
root@9113da5c984f:~#
进入
pintos/src/threads/build/目录:1
cd pintos/src/threads/build/
1
root@4aedfa24dc44:~/pintos/src/threads/build#
开始测试:
1
make check
测试大约需要20~30s,看到输出结果最后类似于以下,说明你到目前为止的操作没有问题:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30pass tests/threads/alarm-single
pass tests/threads/alarm-multiple
pass tests/threads/alarm-simultaneous
FAIL tests/threads/alarm-priority
pass tests/threads/alarm-zero
pass tests/threads/alarm-negative
FAIL tests/threads/priority-change
FAIL tests/threads/priority-donate-one
FAIL tests/threads/priority-donate-multiple
FAIL tests/threads/priority-donate-multiple2
FAIL tests/threads/priority-donate-nest
FAIL tests/threads/priority-donate-sema
FAIL tests/threads/priority-donate-lower
FAIL tests/threads/priority-fifo
FAIL tests/threads/priority-preempt
FAIL tests/threads/priority-sema
FAIL tests/threads/priority-condvar
FAIL tests/threads/priority-donate-chain
FAIL tests/threads/mlfqs-load-1
FAIL tests/threads/mlfqs-load-60
FAIL tests/threads/mlfqs-load-avg
FAIL tests/threads/mlfqs-recent-1
pass tests/threads/mlfqs-fair-2
pass tests/threads/mlfqs-fair-20
FAIL tests/threads/mlfqs-nice-2
FAIL tests/threads/mlfqs-nice-10
FAIL tests/threads/mlfqs-block
20 of 27 tests failed.
../../tests/Make.tests:26: recipe for target 'check' failed
make: *** [check] Error 1
完成!
至此,你的安装和调试过程就已经全部完成了!
建库与合作
由于项目很大很难,所以强烈建议用Github完成:这样一方面完成了团队合作,另一方面也做了版本控制。仓库需要一定的管理,否则极容易发生混乱。建议的管理方式如下:
- 初始仓库内仅有原始的PintOS源代码,存在
main分支下,以后不再修改; - 每次开始一个新的Project时,继承上一个project的分支,建立新的分支,然后在新的分支内完成代码编写;
- 待上一个Project代码稳定后,保证代码不再修改后再建立新的分支,开始下一个Project。
记得频繁Commit!这样可以有效减少合作冲突!
由于笔者记不太住Git命令,所以在此附上常用的命令:
git status查看仓库状态git branch查看当前在哪个分支下git checkout proj1_threads进入本地仓库已有的分支proj1_threadsgit checkout -b proj1_threads复制当前分支所有内容进入新分支proj1_threads,并进入新分支git pull拉取当前分支下所有内容git add .添加本地目录下所有文件进入暂存区git commit -m "comments" -m "description"提交暂存区内容到本地仓库(引号是命令的一部分)git push -u origin proj1_threads将本地仓库当前分支内容推送到远端仓库新建分支proj1_threads(请保证本地仓库与远端仓库名称一致!)git push将本地仓库当前分支内容推送到远端仓库对应的分支上
需要了解的内容
Pintos 目录简介
threads/- 基础内核的源代码,从Project 1开始你将修改此部分。
userprog/- 用户程序加载器的源代码,从Project 2开始你将修改此部分。
vm/- 一个几乎为空的目录。你将在Project 3中在此实现虚拟内存。
filesys/- 基础文件系统的源代码。从Project 2开始你将使用此文件系统,但直到Project 4才会修改它。
devices/- I/O设备接口的源代码:键盘、计时器、磁盘等。你将在Project 1中修改计时器实现。除此之外,你无需更改此部分。
lib/- 标准C库子集的实现。从此目录编译的代码从Project 2开始会同时被编译进Pintos内核及其下运行的用户程序中。在内核代码和用户程序中,均可使用
#include <...>符号包含此目录中的头文件。你基本不需要修改此部分。
- 标准C库子集的实现。从此目录编译的代码从Project 2开始会同时被编译进Pintos内核及其下运行的用户程序中。在内核代码和用户程序中,均可使用
lib/kernel/- 仅包含在Pintos内核中的C库部分。同时包含了一些你可以在内核代码中自由使用的数据类型的实现:位图、双向链表和哈希表。在内核中,可以使用
#include <...>符号包含此目录中的头文件。
- 仅包含在Pintos内核中的C库部分。同时包含了一些你可以在内核代码中自由使用的数据类型的实现:位图、双向链表和哈希表。在内核中,可以使用
lib/user/- 仅包含在Pintos用户程序中的C库部分。在用户程序中,可以使用
#include <...>符号包含此目录中的头文件。
- 仅包含在Pintos用户程序中的C库部分。在用户程序中,可以使用
tests/- 各项目的测试代码。如果有助于测试你的提交,你可以修改此处的代码。评分时,在运行测试前会将
tests/目录替换为原始版本。
- 各项目的测试代码。如果有助于测试你的提交,你可以修改此处的代码。评分时,在运行测试前会将
examples/- 从项目2开始使用的示例用户程序。
misc/和utils/- 如果你尝试在自己的机器上使用Pintos,这些文件可能会派上用场。否则,你可以忽略它们。
更详细内容请参阅:Build and Run | Pintos
Build
要构建项目,只需要 cd进入某个项目目录(如 threads/, userprog/, vm/, filesys/等),然后键入指令:
1 | make |
等待20~30s即构建完成!
有关构建项目产生的文件具体用途,更详细内容请参阅:Building Pintos | Pintos
Run
要执行指令,可以按照以下规则输入指令:
1 | pintos [工具选项] -- [内核参数] |
其中,[工具选项] 部分为可选项(可以不写,也可以串接写很多个):
--bochs使用Bochs代替默认的Qemu来模拟计算机;Bochs更适合Debug时使用,而Qemu大多数情况下跑得更快--gdb用Debug模式运行-m 128设置内存大小为128MB-v关闭VGA显示,仅输出结果--bochs -t使用终端作为VGA显示-s禁用输入输出,避免交互,仅输出结果
[内核参数] 部分可以有如下内容:
run alarm-multiple指将run alarm-multiple作为参数传给PintOS系统,由系统响应这个指令,即运行指定的测试:alarm-multiple
所以总体上一个合法的输入可以是:
1 | pintos -v -- run alarm-multiple |
要想关闭进程,可以 Ctrl + C强制停止。
另外,获取更全的参数表可以键入:
1 | pintos -h |
更详细内容请参阅:Running Pintos | Pintos
Test
现在似乎只能一次性测试所有数据点,不过功能上完全覆盖测试单个数据点,只不过测试时间略长一点。测试过程如下:
先完成项目构建,然后进入项目目录:
1
cd pintos/src/threads/build
跑测试:
1
make check
测试结果会直接显示出来,每个数据点具体的错误信息保存在具体项目目录下,如
pintos/src/threads/build/tests/threads等从第二次测试开始,每次测试之前需要先手动删除该文件夹,如
pintos/src/threads/build/tests/threads等
pintos/src/tests下的各个目录分别代表各个项目的测试程序目录,其中存有评测数据生成器和评测机等;可以手动修改部分评测机数据点进行本地测试,不过最终会以原数据点结果计分。
更详细的内容请参阅:Testing | Pintos
Debug
支持使用 printf()和 ASSERT来辅助Debug。
可以使用 Backtrace来Debug,具体操作详见Debugging | Pintos.
使用GDB来Debug:
先正常启动Docker,然后在
终端1上启动Ubuntu系统;打开
终端2,键入:1
docker exec -it pintos bash
这样就成功在两个终端上进入同一个Ubuntu容器了。
接下来在
终端1上先make构建项目,然后进入项目目录(如pintos/src/threads),键入带--gdb选项的运行指令,如:1
pintos --gdb -- run alarm-multiple
然后
终端1会进入gdb模式,显示类似于这样的内容:1
qemu-system-i386 -device isa-debug-exit -drive format=raw,media=disk,index=0,file=/tmp/2yFkc39zD1.dsk -m 4 -net none -nographic -gdb tcp::1234 -S
接下来在
终端2上进入项目目录中的build文件夹(如pintos/src/threads/build),键入:1
gdb kernel.o
此时
终端2就成功进入gdb模式了,显示类似于这样的内容:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from kernel.o...done.
(gdb)接下来在
终端2中键入:1
target remote localhost:1234
此时
终端2成功连接上本机端口1234,显示类似于这样的内容:1
2
3Remote debugging using localhost:1234
0x0000fff0 in ?? ()
(gdb)这样gdb的配置就完成了。
接下来就可以在
终端2上调试代码了。以下是一些gdb调试指令:程序控制
c/continue
继续运行程序si
单步执行一条汇编指令ni
单步执行一条汇编指令(不进入调用)s/step
单步执行一行源码(进入函数)n/next
单步执行一行源码(不进入函数)finish
运行到当前函数返回quit
退出 GDB
断点
b <function>
在函数入口设置断点b <file>:<line>
在指定文件行号设置断点info break
查看所有断点disable <n>
禁用编号为 n 的断点enable <n>
启用编号为 n 的断点delete <n>
删除编号为 n 的断点delete
删除所有断点
调用栈 / 执行上下文
bt
显示调用栈(backtrace)frame <n>
切换到第 n 层栈帧info frame
查看当前栈帧信息
变量 / 表达式
p <expr>
打印变量或表达式p/x <expr>
以十六进制打印set var <var>=<value>
修改变量值info locals
查看当前函数的局部变量info args
查看当前函数参数
寄存器
info registers
查看所有寄存器info registers eip esp ebp
查看指定寄存器p $eip
打印寄存器值
内存 / 指令查看
x/10i $eip
查看当前指令地址开始的 10 条汇编x/16x <addr>
以十六进制查看内存x/4w <addr>
以 word 形式查看内存disassemble <function>
反汇编函数
源码查看
list
显示当前源码附近list <function>
显示函数源码list <file>:<line>
显示指定位置源码
线程
info threads
查看所有线程thread <n>
切换到指定线程
终端2退出:键入quit或按下Ctrl + D,并确认退出终端1退出:可以先按下Ctrl + A,松开后再按下X关闭进程
更详细的内容请参阅:Debugging | Pintos
评分
在Ubuntu系统内、项目目录下(如 pintos/src/threads),在构建、运行结束后,可以键入:
1 | make grade |
以自动计算当前结果对应的分数和每个测试点的详细得分情况。
更详细的内容请参阅:Grading | Pintos
至此,Project 0,即写代码之前的必要准备就已经全部完成了!准备迎接代码之旅吧!
- 标题: CS130 操作系统I Project 0 准备工作
- 作者: aaaaa
- 创建于 : 2026-02-04 15:00:00
- 更新于 : 2026-02-05 20:29:27
- 链接: https://redefine.ohevan.com/2026/02/04/零基础速通:CS130 操作系统I_3/
- 版权声明: 版权所有 © aaaaa,禁止转载。