CS162笔记第二章(操作系统)

csdiy实验

一、课程开篇:回顾上一讲核心

上一讲我们讲了操作系统的三大角色

  1. 裁判(Referee)

    管理资源、保护、隔离、权限,不让进程互相干扰。

  2. 幻术师(Illusionist)

    把丑陋硬件变成干净、易用的虚拟资源(线程、地址空间、文件等)。

  3. 粘合剂(Glue)

    提供统一服务(窗口、文件系统、网络),让写程序更简单。

老师强调:

同一个物理硬件上,可以同时运行多个进程,每个进程都以为自己独占整台机器。

进程之间禁止互相访问 / 修改对方状态,也不能非法修改操作系统或存储。

一旦违规 → 操作系统直接终止进程 → 段错误(segmentation fault)


二、硬件为什么极度复杂?

老师用 Skylake 处理器架构 举例:

  • CPU 直连高带宽 DRAM、高速显卡
  • 通过 DMI 接口连接 PCH 芯片组(原南桥)
  • 下面挂着:PCIe 高速设备、磁盘、USB、网口、音频、raid 等
  • 再下层还有更低速的设备

结论:

硬件极其杂乱、多样、复杂 → 必须由操作系统来管理与抽象


三、系统复杂度的直观体现:代码行数

  • Linux 从 2.2 到 3.1,代码量增长 6 倍以上

  • 现代汽车:约 1 亿行代码

  • 设备驱动(第三方开发)是

    BUG 重灾区

    统计:超过

    50%~60% 的系统崩溃来自驱动程序

  • 安全漏洞:Spectre、Meltdown(投机执行导致内核数据泄露)

老师核心观点:

操作系统的根本意义:抽象硬件、驯服复杂度


四、操作系统如何 “化繁为简”?(核心抽象)

硬件太烂 → OS 换成更好用的虚拟概念:

  • 物理 CPU → 线程(Thread)
  • 物理内存(零散 DRAM)→ 地址空间(Address Space)
  • 磁盘 / SSD 裸数据块 → 文件系统(File System)
  • 原始网络包 → Socket 接口
  • 裸机 → 进程(Process)

五、本节课正式内容:操作系统 四大基本概念(必考)

老师明确:今天讲 4 个 OS 最基础概念,全程围绕它们展开。


概念一:线程(Thread)— 执行流

1. 线程是什么?

线程 = 一个独立的执行上下文(execution context)

包含:

  • 程序计数器(PC)
  • 寄存器集合
  • 执行标志(flags)
  • 栈(stack)
  • 相关内存状态

2. 线程 = 虚拟化的 CPU(核心)

你在 61C 学的是物理 CPU 的取指执行。

OS 把它虚拟化 → 变成线程

3. 常驻(resident)是什么意思?

当线程的 上下文在 CPU 寄存器里,它就是正在运行、常驻的。

一个核(core)同一时刻只能有一个线程常驻

4. 线程挂起(suspended)

  • 上下文不在寄存器里
  • 被保存到内存中的 TCB(Thread Control Block,线程控制块)
  • 程序计数器不再指向它

5. 多线程 “并发” 幻觉怎么实现?

单 CPU = 时分多路复用(time multiplexing)

  • 运行线程 A 一小会儿
  • 切换
  • 运行线程 B 一小会儿
  • 切换
  • 运行线程 C…

因为切换极快 → 人感觉 “同时运行”。

6. 上下文切换(context switch)做什么?

  1. 把当前线程所有寄存器、PC、栈指针保存到内存 TCB
  2. 加载下一个线程的上下文到 CPU
  3. 开始执行新线程

切换耗时:几微秒

不能切换太快,否则大部分时间都在切换(颠簸 /thrashing)。


概念二:地址空间(Address Space)

1. 定义

地址空间 = 程序可访问的所有地址集合 + 对应状态

例:32 位地址空间

0 ~ 0xFFFFFFFF(约 4GB)

2. 地址空间内部布局

  • 代码段(text/code):指令
  • 静态数据段(data):全局变量、静态变量、字符串常量
  • 栈(stack):局部变量、函数调用
  • 堆(heap):malloc 分配的内存

3. 早期简单保护:基址 + 界限(Base + Bound)

最早的硬件保护方案:

  • 两个寄存器:基址、界限
  • 程序只能访问 [base, bound] 之间的内存
  • 访问越界 → 直接报错

优点:简单、硬件成本低

缺点:扩展麻烦、会产生内存碎片

4. 进阶:地址翻译(虚拟内存)

后面课程重点:

把程序使用的 虚拟地址 → 页表翻译 → 物理地址

  • 无碎片
  • 可以离散存放
  • 可以置换到磁盘
  • 可以隔离保护

概念三:进程(Process)— 本讲最重要

1. 进程是什么?

进程 = 带权限限制的执行环境

= 保护后的地址空间 + 一个或多个线程 + 文件等资源

2. 为什么需要进程?

早期只有线程:

  • 所有线程共享同一份地址空间
  • 一个线程崩溃 → 全盘崩溃
  • 线程可互相改写内存、窃取数据
  • 线程可以改写操作系统 → 系统直接挂掉

进程 = 隔离 + 保护 + 权限

3. 进程核心特性

  • 每个进程有独立地址空间
  • 进程之间无法互相访问
  • 一个进程崩了 → 不影响其他
  • OS 受保护,不会被随意破坏

4. 进程 vs 线程(老师反复强调)

  • 进程:资源容器、保护单位(地址空间、文件、权限)
  • 线程:执行单位、活跃单位(PC、寄存器、栈)
  • 一个进程至少有一个线程
  • 同一进程内的线程共享地址空间
  • 不同进程完全隔离

概念四:双重模式(Dual Mode)— 安全基石

1. 处理器至少两种模式:

  1. 内核模式(Kernel Mode / Supervisor)

    • 全权访问所有资源
    • 可以修改页表、关中断、操作硬件
  2. 用户模式(User Mode)

    • 权限受限
    • 不能修改页表
    • 不能关中断
    • 不能直接访问硬件

2. 为什么需要双模式?

防止用户程序:

  • 霸占 CPU(死循环不放手)
  • 破坏操作系统
  • 访问别的进程数据
  • 随意操控硬件

3. 如何进入内核模式?(仅三种合法入口)

  1. 系统调用(system call):进程主动请求服务
  2. 中断(interrupt):时钟、磁盘、网络等事件
  3. 异常 / 陷阱(exception/trap):除零、缺页、非法访问

→ 所有入口都由操作系统严格控制


六、完整运行模型(老师最终总结图)

  1. 程序从磁盘加载

  2. 操作系统创建

    进程

    • 分配独立地址空间
    • 建立页表
    • 分配栈、堆
  3. 从入口开始执行,运行在用户模式

  4. 需要服务 → 系统调用 → 进入内核模式

  5. 内核完成操作,返回用户态

  6. 时钟中断触发 → 操作系统切换进程


七、本节课所有管理与作业提醒(全覆盖)

  • 作业 0(Homework 0):立刻开始,熟悉工具、GDB、编译、虚拟机
  • Project 0:明天发布,独立完成,不许合作
  • 项目缓交天数(slip days):作业与项目共用 4 天
  • 本周五是 退课截止日期(drop date)
  • 可选 C/C++ 复习课:明天举行
  • 课程全程使用 C 语言,项目在 Pintos 操作系统上开发

八、老师强调的易错点(必看)

  1. 线程不自带缓存,一个核的缓存被所有线程共享
  2. 线程不在 CPU 运行时,状态存在 TCB(内存里)
  3. 进程 = 保护单位;线程 = 执行单位
  4. 没有地址翻译 + 双模式 → 系统完全不安全
  5. 早期系统(Win3.1、Mac 早期)无强保护 → 极易崩溃
  6. 上下文切换需要保存与恢复 全部寄存器

九、本讲最终结论(老师原话总结)

现代操作系统建立在 四大基本概念 之上:

  1. 线程(Thread):执行流、虚拟化 CPU
  2. 地址空间(Address Space):内存视图
  3. 进程(Process):受保护的执行环境
  4. 双重模式(Dual Mode):内核态 / 用户态,安全基础

它们一起实现:虚拟化、隔离、保护、并发