操作系统 进程(4)上下文切换与系统调用
目标问题:
“当系统切换进程时,CPU里到底发生了什么?”
学习重点:
- 上下文切换的过程(保存/恢复寄存器、堆栈指针)
- 系统调用与用户态、内核态的切换机制
- 调度器(Scheduler)在操作系统中的位置与职责
📘 建议思考:
为什么上下文切换太频繁会导致性能下降?(提示:CPU cache 失效、保存/恢复寄存器代价)
🧩 一、什么是上下文(Context)
“上下文”可以理解为:
👉 CPU 执行某个进程时所需的全部状态信息。
包括:
类型 | 内容 | 示例 |
---|---|---|
CPU寄存器 | 程序计数器(PC)、通用寄存器、标志位等 | eax, ebx, eip… |
内存信息 | 栈指针(SP)、页表、段寄存器 | esp, ebp… |
程序状态 | 用户态 / 内核态、调度优先级等 | current_mode |
⚙️ 就像游戏存档:
你退出游戏前要保存主角位置、血量、装备……
CPU 也是在切换前保存“进程的执行现场”。
🔄 二、上下文切换(Context Switch)
定义:
操作系统从一个进程切换到另一个进程的过程。
🧠 举个例子:
假设有两个进程 P1、P2。
P1 正在执行计算任务,此时:
- P1 时间片用完(或触发中断)
- 操作系统暂停 P1
- 把 P1 的寄存器、程序计数器、栈指针等信息保存到 P1 的PCB(进程控制块)
- 从就绪队列中选中 P2
- 把 P2 之前保存的寄存器状态、计数器等信息恢复到 CPU 寄存器
- CPU 从 P2 停下的那一条指令继续执行
📍这个“保存 + 恢复”的动作,就是 上下文切换。
📦 三、上下文切换的开销
切换并不是“免费”的!
代价主要来自:
- 寄存器保存与恢复
保存几十个寄存器状态,恢复另一个进程的状态; - 内核态切换
切换需要进入内核态执行; - 缓存失效(Cache Miss)
CPU Cache 里是上一个进程的数据,新进程要重新加载; - TLB(页表缓存)失效
虚拟内存页表切换后,也要刷新。
💡 所以:
“过于频繁的上下文切换 = 时间浪费在切人上,不在干活上。”
举个形象比喻:
- 每个人都只说一句话就换人,会议效率极低;
- 给每人多点时间说完一句完整的话,再换人,效率更高。
(这就是时间片设计的平衡思想)
🧱 四、系统调用(System Call)
操作系统是内核(Kernel),而普通程序在用户态(User Mode)。
用户态程序不能直接操作硬件,比如访问磁盘、网络、I/O 设备。
于是它必须请求内核代为执行 —— 这就叫系统调用。
🔒 用户态与内核态的区别
项目 | 用户态 | 内核态 |
---|---|---|
权限 | 低,只能执行普通指令 | 高,可执行特权指令 |
可访问内存 | 自己的虚拟内存 | 全系统内存 |
举例 | 应用程序(浏览器、QQ) | 操作系统内核、驱动程序 |
🧩 系统调用过程(比如 read 文件)
- 程序调用
read()
- 通过**软中断(trap)**进入内核态
- 内核检查权限 → 执行文件系统操作
- 把结果(或错误码)返回给用户程序
- CPU 切回用户态,程序继续执行
📍 核心区别在于:
从用户态到内核态,是一次“受控的特权切换”。
🔄 用户态 vs. 上下文切换
操作类型 | 是否切换进程 | 是否切换态 |
---|---|---|
系统调用(read/write) | ❌ 否 | ✅ 用户态 → 内核态(同进程) |
上下文切换 | ✅ 是(换进程) | ✅ 通常也会切换内核态 |
换句话说:
- 系统调用:同一个人,换个身份(普通人→管理员);
- 上下文切换:换了一个人(P1→P2)。
🧭 五、调度器的角色
调度器(Scheduler)是操作系统内核中管理 CPU 分配的核心组件,它负责:
- 挑选哪个进程获得 CPU;
- 控制上下文保存 / 恢复;
- 根据调度策略(FCFS, RR, MLFQ等)决策切换顺序。
💡 调度器 + 上下文切换 = CPU多任务的本质机制。