引言

本章导读

本章展现了操作系统一个功能:让应用与硬件隔离,简化了应用访问硬件的难度和复杂性。

大多数程序员的第一行代码都从 Hello, world! 开始,当我们满怀着好奇心在编辑器内键入仅仅数个字节,再经过几行命令编译(靠的是编译器)、运行(靠的是操作系统),终于在黑洞洞的终端窗口中看到期望中的结果的时候,一扇通往编程世界的大门已经打开。在本章第一节 代码框架简述 中,可以看到用C语言编写的非常简单的“Hello, world”应用程序。

不过我们能够隐约意识到编程工作能够如此方便简洁并不是理所当然的,实际上有着多层硬件和软件工具和支撑环境隐藏在它背后,才让我们不必付出那么多努力就能够创造出功能强大的应用程序。生成应用程序二进制执行代码所依赖的是以 编译器 为主的开发环境;运行应用程序执行码所依赖的是以 操作系统 为主的执行环境。

本章我们将从操作系统最简单但也是最重要的println入手,要求大家实现一个裸机上的println以及带色彩的LOG,如info和warn,error等功能。因为大家是刚刚接触操作系统实验,本章的所有代码已经帮大家写好了,没有大家需要亲自编写代码的部分。但是它作为第一章又是最重要的一个章节:这一章之中,同学们要对整个 C 的 OS 实验框架有一个大致的掌握。对整个框架是如何编译的,之后需要写哪些内容以及如何测试有一个基本的认识。可以说,ch1 打好基础会使得之后的实验难度大大降低。

系统调用

在实验开始之前,大家要熟悉一下系统调用(syscall)的概念。相信大家在汇编的课程中一定接触过这个名词。我们 OS 课程中的 syscall 的意义也是一样的,它是操作系统提供给软件的一系列接口,使得软件能够使用系统的功能。syscall 本质上属于一种异常/中断,它在 riscv 的汇编指令中以 ecall 的形式出现。

本章的 println 所需要的在 console 中打印字符,也需要调用到 syscall。syscall 的种类有很多,操作系统通过区分 syscall 的 id 来判断是哪一个syscall。

实践体验

获取本章代码:

$ git checkout ch1

在 qemu 模拟器上运行本章代码,看看一个小应用程序是如何在QEMU模拟的计算机上运行的:

$ make run LOG=trace

警告

FIXME: 提供 wsl/macOS 等更多平台支持

如果顺利的话,以 qemu 平台为例,将输出:

../_images/ch1-demo.png

除了 Hello, world! 之外还有一些额外的信息,最后关机。

注解

RustSBI是啥?

附录 C:深入机器模式:RustSBI 可以进一步了解RustSBI。

展望未来

现在我们的 os 会直接关机,在我们完成 lab5 之后,我们的 os 就可以比较自由的运行用户程序了。具体来说,我们会有一个 shell.

../_images/color-demo.png