前言

Stanford 的 CS144 计网完成后让我们继续挑战一项更难的课程项目:UCB 操作系统 CS162 的 Pintos,这个也是多个 CS 顶校都在用的项目。老规矩讲课部分因为本科基本都学过就略过了。

继续安利 CS自学指南,和博主同届甚至就住在楼下的大佬的自学网站,汇总了很多国内外高校 CS 相关的高质量公开课。

项目内容为理解一个微型操作系统 Pintos 的原理并为其添加几方面的重要功能,有自动化测试样例。可以跟着北大操作系统实验班整理的文档做:PintosBook

我的实现(更新至Lab 2):Altair-Alpha/pintos

准备工作

环境配置

跟着实验手册的 Environment Setup 做即可,博主用的是 Docker 部署,未出现问题。开发环境 VSCode + 开两个 PoweShell 窗口一个运行一个调试就很舒服了。

预备知识

  • C 语言基础。
  • 大体过一遍实验手册的 Getting Started 和 Appendix 部分,如果有整块没接触过的知识可以补一补。每个 Lab 中会提示需要详细阅读的部分。
  • 如果没有学过汇编,可以读 PCASM 这本书,不需要记住所有汇编指令的具体细节,大概能看懂程序意思即可。
  • GDB 调试。本课程是一次非常好的学习和锻炼调试程序的机会,本节 Lab 0 主要就是一个利用调试观察系统启动流程的热身,请仔细阅读手册中的 Debugging 部分,也可以参考 C 语言中文网上的 GDB 调试教程 。

Task 1: Booting Pintos

成功启动 Pintos 即可。下面游戏正式开始。

Task 2: Debugging

Exercise 2.1

  • What is the first instruction that gets executed?
  • At which physical address is this instruction located?

按照 Debugging 部分说明运行 GDB 绑定 Pintos 后得到以下输出,即机器启动运行的第一条指令:

[f000:fff0]    0xffff0: ljmp   $0x3630,$0xf000e05b

该指令为 ljmp(长转移),位于 0xffff0,属于 BIOS 区内,是硬编码的第一条指令位置。

Exercise 2.2

0x7c00 处设置断点并运行到该位置,此时控制权已由 BIOS 移交给 Bootloader,运行的指令与 loader.S 文件相对应。

  • How does the bootloader read disk sectors? In particular, what BIOS interrupt is used?

第 55 行,指令为 call read_sector,调用的函数位于 230 行:


读取硬盘扇区需要借助 BIOS 提供的功能,具体来说就如题面所述是触发一个 BIOS 中断,该指令位于 242 行(图中红框),维基百科 BIOS interrupt call 条目下有完整的中断表可供查询:

结合 240 行对 AH = 0x42 的设置可知使用的是 Extended Read Sectors 功能。

  • How does the bootloader decide whether it successfully finds the Pintos kernel?

继续向下看,目前我们已经读取了第一个磁盘扇区的内容,该扇区应该为主引导记录(Master Boot Record, MBR)扇区,包含了磁盘的分区信息,其特征是以 0x55AA 标志位结束(位于 0x01FE - 0x01FF,即 510,511 字节处)。67 行进行该检查,如果不相等,说明当前磁盘未正常分区,跳过并读取下一个磁盘。接下来跳转到 MBR 中第一个分区记录的位置(offset=446),如果读取结果为 0,说明当前分区未使用,使 si+=16 读取下一个分区记录,如果达到结束位置(510)仍未找到有效分区,则跳转至下一个磁盘。然后根据注释使用了值 0x20 来检查是否为 Pintos Kernel,这里我没有在文档中找到相应说明。最后,检查分区记录中第一个字节的值,该值如果为 0x80 则标识着当前分区是 Bootable 的。



至此,如果所有检查均通过,则可以确信已经找到了 Pintos Kernel。

  • What happens when the bootloader could not find the Pintos kernel?

接续上一个问题的分析,如果所有分区、所有磁盘均尝试读取后都没有找到 Pintos Kernel 并执行 86 行跳转到 load_kernel 函数,则最终会落入:

输出 Not found 后,会触发另一个 BIOS 中断 0x18,该中断的作用即 Bootloader 向 BIOS 报告因未找到可引导磁盘导致启动失败。

  • At what point and how exactly does the bootloader transfer control to the Pintos kernel?

找到 Pintos Kernel 后,Bootloader 从磁盘逐个读取扇区内容,并放在从 0x20000 开始的内存空间。Kernel 以 ELF 格式存储,如文档所述,Kernel 的入口位置非固定编码,而是被保存在其 ELF Header 中的一个指针。该指针位于 0x18,于是第 165 行指令读取该指针放在寄存器 dx 中,又在 166 行将其转存在一个内存位置 start 中(注释中解释了这样做的原因),最终在 168 行执行 ljmp 实际跳转。


至此,Bootloader 的使命完成,控制权移交给 Pintos Kernel 的入口。该入口就是 start.S 文件中的汇编代码。这部分代码完成了内存识别、页表建立、GDT 处理以及从 16-bit real mode 到 32-bit protected mode 的转换等工作,对应文档中 Core Guide / Loading / Low-Level Kernel Initialization 部分,这里就不再展开了。最终在 180 行执行 call pintos_init,该函数位于 init.c 中,进入 C 语言代码。

Exercise 2.3

此部分主要练习 GDB 使用,为后续 Lab 打基础。追踪的目标为 init.c 中的一个函数 palloc_get_page() 和一个全局变量 uint32_t *init_page_dir

  • At the entry of pintos_init(), what is the value of the expression init_page_dir[pd_no(ptov(0))] in hexadecimal format?

pintos_init 起始处设置断点,并计算该表达式,结果为 0。

  • When palloc_get_page() is called for the first time,

    • what does the call stack look like?
    • what is the return value in hexadecimal format?
    • what is the value of expression init_page_dir[pd_no(ptov(0))] in hexadecimal format?

bpalloc_get_page 处设置断点,c 运行至该位置,然后使用 bt 查看调用栈。使用 finish/fin 运行至函数结束并查看返回值是一个 void * 指针。使用 p/x 打印表达式 16 进制计算结果,仍为 0。

  • When palloc_get_page() is called for the third time,
    - what does the call stack look like?
    - what is the return value in hexadecimal format?
    - what is the value of expression init_page_dir[pd_no(ptov(0))] in hexadecimal format?

继续 c 两次,重复上一步操作得到:


可以观察到,本次调用与第一次不同,不是在 paging_init 中而是在 thread_start 中被调用。返回的 void * 指针与第一次相差 0x2000。表达式的值为 0x102027

Task 3: Kernel Monitor

Exercise 3.1

在 Lab 0 的最后,我们可以上手在 Pintos 中写入一些自己的代码了。目前,如果在 Pintos 启动的命令行中没有参数,则启动后会自动结束。本节的任务是在这种情况下添加一个可交互的终端,要求如下:

Enhance threads/init.c to implement a tiny kernel monitor in Pintos.
Requirments:

  • It starts with a prompt PKUOS> and waits for user input.
  • As the user types in a printable character, display the character.
  • When a newline is entered, it parses the input and checks if it is whoami. If it is whoami, print your student id.
  • Afterward, the monitor will print the command prompt PKUOS> again in the next line and repeat.
  • If the user input is exit, the monitor will quit to allow the kernel to finish. For the other input, print invalid command. Handling special input such as backspace is not required.
  • If you implement such an enhancement, mention this in your design document.

这里首先要注意,我们是在 Kernel 层级编写代码,所以标准 C 库函数是 不能使用 的,不过课程为我们预先写好了一些与 C 同名的库函数,位于 lib 文件夹下,并且配置好了头文件搜索路径。

代码实现(包含 Backspace 键处理):

int
pintos_init (void)
{...if (*argv != NULL) {/* Run actions specified on kernel command line. */run_actions (argv);} else {size_t cmd_maxlen = 10;char *buf = (char *)malloc(cmd_maxlen); // command line input bufferwhile (true) {printf("PKUOS>");memset(buf, '\0', cmd_maxlen);size_t index = 0;while (1) {char c = input_getc();if (c == 13) { // newlineprintf("\n");break;} else if (c == 127) { // backspaceif (index > 0) {buf[--index] = '\0';printf("\b \b");}continue;}if (index >= cmd_maxlen) {continue;}buf[index++] = c;if (c > 31) { // printable charactersprintf("%c", c);}}printf("cmd: %s\n", buf);if (!strcmp(buf, "whoami")) {printf("123456789\n");} else if (!strcmp(buf, "exit")) {break;} else {printf("invalid command\n");}}free(buf);printf("shell terminated.\n");}...
}

Lab 0 至此结束。

【UCB操作系统CS162项目】Pintos Lab0:项目上手 (Getting Real)相关推荐

  1. 【UCB操作系统CS162项目】Pintos Lab2:用户程序 User Programs(下)

    在上节中,我们已经完成了 Lab 2 要求的参数传递和系统调用中的 halt, exit 以及向 stdout 输出的 write,最终停在了 wait 的实现之前.本节就先从 wait 和 exec ...

  2. 【UCB操作系统CS162项目】Pintos Lab2:用户程序 User Programs(上)

    本节 Lab 2 复杂度有所上升,考虑到文章太长影响观感且有些劝退,博主决定拆成上下两部分来写╰( ̄▽ ̄)╭ 以下内容大部分都是博主自己的理解,因为本节开始网上能参考的代码明显变少了(很多文章都在解释 ...

  3. 【UCB操作系统CS162项目】Pintos Lab1:线程调度 Threads

    实验文档链接:Lab1: Threads 我的实现(更新至Lab 2):Altair-Alpha/pintos 开始之前 如文档所述,在开始编写代码之前需要先阅读掌握 GETTING STARTED ...

  4. 信创操作系统--麒麟Kylin桌面版 (项目七 网络连接:有线、无线网络)

    信创操作系统–麒麟Kylin桌面版 (项目七 网络连接:有线.无线网络) 目录 1. 有线网络 1.1开启有线网络功能 1.2设置有线网络功能 2. 无线网络 2.1 连接无线网络 2.2 连接隐藏无 ...

  5. 信创操作系统--麒麟Kylin桌面版 (项目二 桌面环境)

    信创操作系统–麒麟Kylin桌面版 (项目二 桌面环境) 目录 桌面布局 新建文件夹/文档 设置排序方式 调整图标 设置显示器 壁纸与屏保 剪贴板 任务栏 回收站 开始菜单 开始菜单模式 应用管理 窗 ...

  6. Linux综合实训案例教程,Linux操作系统教程-实训与项目案例原稿.ppt

    Linux操作系统教程-实训与项目案例原稿分析 第11章 Bash 使用详解 本章内容 Shell概念 Linux下用户Shell的指定 Bash的使用 Bash的常见技巧与快捷键 Bash的变里使用 ...

  7. 头条号搬运项目,小白简单上手日入200+

    头条号搬运项目,小白简单上手日入200+ 大家好,我是独孤求胜,公众号独孤思维.今天是原创日更84篇. 上次分享了一个头条号音频近期收益截图,很多粉丝跑来问我,头条居然还可以赚钱?居然还可以音频赚钱? ...

  8. 分享一份软件测试项目(Python项目)

    在之前小编分享的众多项目中,以Java项目或PHP项目居多,Python项目很少,但有的小伙伴又想要找Python项目练手. 为了满足小伙伴们的需求,凭实力宠粉,小编这次免费跟大家分享一个Python ...

  9. 操作系统课程设计pintos project1实验摘记

    前言: 本篇意在记录本学期结束的操作系统课程设计pintos project1实验报告和实现过程.整个实验参考了多篇文章也查阅了一些代码,其中部分内容或与其他文章相同,还请见谅.同时,也为了测试CSD ...

最新文章

  1. mysql-connector-net不同版本下载
  2. 网站安装打包 软件环境检测与安装[二] 下
  3. python怎么清空屏幕_python如何清屏
  4. HMM和CRF 条件随机场详解
  5. 使用RMAN备份数据库和归档日志合二为一
  6. Android 解压zip文件
  7. 20200616:力扣193周周赛上
  8. 在发送邮件HTML中,CSS等问题
  9. 第03讲- 第一个Android项目
  10. 2021年认证杯SPSSPRO杯数学建模B题(第一阶段)依巴谷星表中的毕星团求解全过程文档及程序
  11. 商务英语计算机,怎样练习商务英语口语
  12. 经典对抗攻击Deepfool原理详解与代码解读
  13. subclipse 下载地址
  14. 中学计算机课程课时,高中信息技术教案word操作(共5份8课时
  15. 【成电860考研】《软件工程》-anki卡片知识合集-504张卡片-28000字-上岸资料整理
  16. VirtualBox-ubuntu系统下挂载U盘
  17. SketchUp 2021(草图大师)新增功能
  18. Xftp上传文件状态错误的解决方法
  19. blender快捷键(持续更新)
  20. 人工神经网络的应用实例,人工神经网络实际应用

热门文章

  1. 数据科学项目的完整流程介绍
  2. 计算机导论相关ppt,计算机导论PPT 数制.ppt.ppt
  3. <LandingSite>Focusing Locator识别定位器ID
  4. 记录一次Etcher镜像刷写不成功的bug
  5. 小米也要造车了?为何手机厂商也爱造车?
  6. 倍福TwinCAT(贝福Beckhoff)基础教程4.2 TwinCAT如何读写CSV文件
  7. ios 中文输入法 完成事件_compositionEnd 和 input 事件(中文输入法问题)
  8. 如何在Arcmap中添加点线面要素
  9. PreScan第五课:检测车辆碰撞
  10. 自动存包柜c语言程序,基于单片机的自动存包柜设计.doc