操作系统的状态机模型 (操作系统的加载; thread-os 代码讲解)
【操作系统的状态机模型 (操作系统的加载; thread-os 代码讲解) [南京大学2022操作系统-P9]】https://www.bilibili.com/video/BV1yP4y1M7FE
https://jyywiki.cn/OS/2022/slides/9.slides#/1/2
本学期的 OSLabs
热身实验
- Lab0 (amgame): 熟悉代码框架
正经实验
- Lab1 (pmm): Physical memory management
- 多处理器 (bare-metal) 上的 kalloc/free
- Lab2 (kmt): Kernel multi-threading
- 中断和异常驱动的上下文 (线程) 切换
- Lab3 (uproc): User processes
- 虚拟地址空间、用户态进程和系统调用
- Lab4 (vfs): Virtual file system
- devfs, procfs, 简单的文件系统;ELF 加载器
大学的真正意义
将已有的知识和方法重新消化,为大家建立好 “台阶”,在有限的时间里迅速赶上数十年来建立起的学科体系。
今天的学术界可比 Bill Gates 的时代卷多了
- 学术界基本没啥是需要一个毛头小伙子来教的
例子:破除 “写操作系统很难”、“写操作系统很牛” 的错误认识
- 操作系统真的就是个 C 程序
- 你只是需要 “被正确告知” 一些额外的知识
- 然后写代码、吃苦头
- 从而建立正确的 “专业世界观”
例子
“专业世界观” 的例子 (这些都没啥,paper 都发不了)
- 写 x86 模拟器的时候,不知道哪条指令错了,怎么办?
- 做操作系统实验的时候,如果遇到神秘 CPU Reset,怎么办?
- 做实验做不下去的时候,该实现什么工具?
“专业世界观” 的学习方法
- 经典研究论文 (OSDI, SOSP, ATC, EuroSys, ...)
- 久经考验的经典教学材料 (xv6, OSTEP, CSAPP, ...)
- 海量的开源工具 (GNU 系列, qemu, gdb, ...)
- 第三方资料,慎用 (tutorials, osdev wiki, ...)
硬件和软件的桥梁
C 程序
我们已经知道如何写一个 “最小” 的 C 程序了:
- minimal.S
- 不需要链接任何库,就能在操作系统上运行
“程序 = 状态机” 没问题
- 带来更多的疑问
- 但谁创建的这个状态机???
- 当然是操作系统了……呃……
- 这个程序可以在没有操作系统的硬件上运行吗?
- “启动” 状态机是由 “加载器” 完成的
- 加载器也是一段程序 (状态机)
- 这个程序由是由谁加载的?
- 但谁创建的这个状态机???
Bare-metal 与程序员的约定
为了让计算机能运行任何我们的程序,一定存在软件/硬件的约定
- CPU reset 后,处理器处于某个确定的状态
- PC 指针一般指向一段 memory-mapped ROM
- ROM 存储了厂商提供的 firmware (固件)
- 处理器的大部分特性处于关闭状态
- 缓存、虚拟存储、……
- PC 指针一般指向一段 memory-mapped ROM
- Firmware (固件,厂商提供的代码)
- 将用户数据加载到内存
- 例如存储介质上的第二级 loader (加载器)
- 或者直接加载操作系统 (嵌入式系统)
- 将用户数据加载到内存
x86 Family: CPU Reset 行为
CPU Reset (Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A/3B)
- 寄存器会有初始状态
EIP = 0x0000fff0
CR0 = 0x60000010
- 16-bit 模式
EFLAGS = 0x00000002
- interrupt disabled
- TFM (5,000 页 by 2019)
- 最需要的 Volume 3A 只有 468 页
Intel® 64 and IA-32 Architectures Software Developer Manuals https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html
CPU Reset 之后:发生了什么?
《计算机系统基础》:不仅是程序,整个计算机系统也是一个状态机
- 从 PC (
CS:IP
) 指针处取指令、译码、执行…… - 从 firmware 开始执行
ffff0
通常是一条向 firmware 跳转的 jmp 指令
Firmware: BIOS vs. UEFI
- 都是主板/主板上外插设备的软件抽象
- 支持系统管理程序运行
- Legacy BIOS (Basic I/O System)
- UEFI (Unified Extensible Firmware Interface)
Legacy BIOS: 约定
Firmware 必须提供机制,将用户数据载入内存
- Legacy BIOS 把第一个可引导设备的第一个扇区加载到物理内存的
7c00
位置- 此时处理器处于 16-bit 模式
- 规定
CS:IP = 0x7c00
,(R[CS] << 4) | R[IP] == 0x7c00
- 可能性1:
CS = 0x07c0, IP = 0
- 可能性2:
CS = 0, IP = 0x7c00
- 可能性1:
- 其他没有任何约束
能不能看一下代码?
Talk is cheap. Show me the code. ——Linus Torvalds
有没有可能我们真的去看从 CPU Reset 以后每一条指令的执行?
计算机系统公理:你想到的就一定有人做到。
- 模拟方案:QEMU
- 传奇黑客、天才程序员 Fabrice Bellard 的杰作
- QEMU, A fast and portable dynamic translator (USENIX ATC'05)
- Android Virtual Device, VirtualBox, ... 背后都是 QEMU
- 传奇黑客、天才程序员 Fabrice Bellard 的杰作
- 真机方案:JTAG (Joint Test Action Group) debugger
- 一系列 (物理) 调试寄存器,可以实现 gdb 接口 (!!!)
调试 QEMU: 确认 Firmware 的行为
亲眼确认 Firmware 到底是不是会加载启动盘第一个扇区到
0x7c00
内存位置!
调试 QEMU 模拟器
- 查看 CPU Reset 后的寄存器
info registers
- 查看
0x7c00
内存的加载watch *0x7c00
- 《计算机系统基础》的良苦用心- 查看当前指令
x/i ($cs * 16 + $rip)
- 打印内存
x/16xb 0x7c00
- 进入
0x7c00
代码的执行b *0x7c00
,c
(撒花!我们一会再回来)