Operating System
操作系统概述
背景回顾:大家已经有多年的操作系统使用经验,也知道 “操作系统” 是一门很重要的课程,但却无法回答 “操作系统到底是什么”、“为什么重要” 这样的问题。我们将在一学期的时间里回答这些问题,并建立操作系统相关的基本概念、思想方法和编程技巧。
本讲内容:个人/课程简介、操作系统的发展历史,回答三个问题:
(Why): 为什么要学操作系统?
(What): 到底什么是操作系统?
(How): 怎么学操作系统?
Take-away Messages
操作系统没有传说中那么复杂 (程序视角:对象 + API,硬件视角:一个 C 程序)
为什么要学操作系统:解锁 “实现一切” 的系统编程能力
什么是操作系统:应用视角 (一组对象 + API)、机器视角 (一个程序)
怎么学操作系统:答案就在代码中
应用视角的操作系统
本讲内容:指令序列和高级语言的状态机模型;回答以下问题:
什么是软件 (程序)?
解决问题
如何在操作系统上构造最小/一般/图形界面应用程序?
不写终止状态的main函数(一个死循环程序减小背后的链接)
操作系统是一个状态机可以通过syscall接管程序,从而改变程序的状态,包括“关闭”
什么是编译器?编译器把一段程序翻译成什么样的指令序列才算 “正确”?
Everything (高级语言代码、机器代码) 都是状态机;而编译器实现了两种状态机之间的翻译。无论何种状态机,在没有操作系统时,它们只能做纯粹的计算,甚至都不能把结果传递到程序之外——而程序与操作系统沟通的唯一桥梁是系统调用 (例如 x86-64 的 syscall 指令)。如此重要的桥梁,操作系统中自然也有工具:strace 可以查看程序运行过程中的系统调用序列。
编译优化?
三板斧:
函数内联:将函数调用替换为函数本身的内容
常量传播:在编译时计算常量表达式的值并替换
死代码消除: 删除永远都不会执行到的代码
应用视角(自顶向下)
操作系统 = 对象 + API
应用通过syscall访问操作系统
M1: 打印进程树 (pstree)
硬件视角的操作系统
背景回顾:操作系统有三条主线:“软件 (应用)”、“硬件 (计算机)”、“操作系统 (软件直接访问硬件带来麻烦太多而引入的中间件)”。我们已经理解了操作系统上的应用程序的本质 (状态机)。而程序最终是运行在计算机硬件上的;因此有必要理解什么是计算机硬件,以及如何为计算机硬件编程。
Everything is statemachine
计算机系统的状态机模型:
状态:
内存、寄存器的数值
初始状态:
由系统设计者规定(CPU Reset)
状态迁移:
从PC取指令执行
计算机系统中的固件:Firmware
运行程序前的计算机系统配置
CPU电压、内存时序、接口开关
不严格的说,可以加载操作系统
Fireware:就是一段代码
一个小“操作系统”
Leagacy BIOS (兼容机) -> UEFI(提供更丰富的支持,例如设备驱动)
机器视角(自底向上)
操作系统 = C程序
运行在计算机硬件上的一个普通程序
数学视角的操作系统
数学视角的程序
程序正确性证明的两种方法
1.暴力枚举,写一个driver code运行所有可能的函数调用序列,如果机器和driver都没用bug,程序就是对的
2.写出数学证明
我们的操作系统和程序都可以看成数学对象:
操作系统 = 状态机的管理者
它也是自己的状态机,有自己的状态
于是,我们可以自己定义状态机,自己模拟状态机的运行,做一个“玩具操作系统”
30行模拟操作系统原理
进程
系统调用
上下文切换
调度
操作系统中的对象
状态机
Python代码
初始时,,只有一个状态机main
允许执行计算或read,write,spawn系统调用
一个进程间共享的buffer(设备)
系统调用
read():返回随机的 0 或 1
write(s): 向buffer输出字符串s
spawn(f): 创建一个可运行的状态机f
L0: 为计算机硬件编程
多处理器编程:从入门到放弃
入门:线程模型和线程库
线程模型
C语言状态机
共享所有全局变量
独立的栈帧列表
汇编语言状态机
共享一个地址空间
独立的寄存器
状态迁移:选择任意一个线程执行一步
放弃:原子性、可见性、顺序
并发控制:互斥
如何实现并发控制的lock() unlock()?
关中断
很危险