2. 应用视角的操作系统

背景回顾:操作系统是连接软件和硬件的桥梁。因此想要理解操作系统,我们首先需要对操作系统的服务对象 (应用程序) 有更精确和深刻的理解。

本讲内容:程序的状态机模型;回答以下问题:

  • 什么是程序?
  • 如何在操作系统上构造最小/一般、甚至是图形界面应用程序?
  • 编译器的工作原理是什么?

2.1 操作系统上的最小应用程序

我们在编程时,总是想象程序 “独占整个计算机,逐条指令执行”,大部分时候都不用 “考虑” 操作系统的存在。当系统调用发生时,程序执行被完全暂停,但操作系统依然在工作——就像麻醉后醒来,周围的环境发生了变化,但我们完全没有感到时间的流逝。

2.2 操作系统上的应用程序

如果你感到 strace 的结果不那么友善,用适当的工具处理它就非常重要了。课堂上我们展示了用命令行工具进行处理的 “传统方法”:

$ strace ls |& grep -e read -e write

对新手来说,感到困惑是非常正常的——但我们总是可以把不熟悉的东西用熟悉的东西类比 (正是 AI 擅长的)。今天你只要学会提问,就几乎总是能得到满意的答案。

2.3 C 语言与汇编

2.4 编译器与编译优化 🌶️

Take-away Messages

Everything (高级语言代码、机器代码) 都是状态机;而编译器实现了两种状态机之间的翻译。无论何种状态机,在没有操作系统时,它们只能做纯粹的计算,甚至都不能把结果传递到程序之外——而程序与操作系统沟通的唯一桥梁是系统调用 (例如 x86-64 的 syscall 指令)。如此重要的桥梁,操作系统中自然也有工具:strace 可以查看程序运行过程中的系统调用序列。

课后习题/编程作业

📚阅读材料

本次课没有书本阅读材料;但你可以花一些时间了解一下相关的源码项目:

  • 浏览 GNU CoreutilsGNU Binutils 的网站,建立 “手边有哪些可用的命令行工具” 的一些印象。
  • 浏览 gdb 文档的目录,找到你感兴趣的章节了解,例如——“Reverse Execution”、“TUI: GDB Text User Interface”……
  • 对于你有兴趣的命令行工具,可以参考 busyboxtoybox 项目中与之对应的简化实现。Toybox 现在已经成为了 Android 自带的命令行工具集。
🖥️编程

在你的 Linux 中运行课堂上的代码示例,包括:

  • 编译链接最小二进制文件,并使用 strace 查看执行的系统调用序列。
  • 尝试将非递归汉诺塔扩展到 ffgg 两个函数互相调用的情况。
  • 使用 strace 查看更多程序的系统调用序列,并在好奇心的驱使下了解一部分系统调用的作用。

在之后的课程中,我们默认你会运行和理解课堂上的代码示例。