操作系统在进行**线程切换(thread context switch)**时,需要保存当前线程的上下文,并恢复目标线程的上下文。这是操作系统调度器的一部分,涉及用户态与内核态之间的协作。
一、线程切换的本质
线程切换 = 上下文切换(Context Switch)的一种
包括:
- 当前线程上下文保存(寄存器、程序计数器等)
- 调度器选择下一个线程
- 恢复目标线程的上下文并运行
二、线程切换与进程切换的区别
项目 | 线程切换 | 进程切换 |
---|---|---|
地址空间 | 相同(共享) | 发生变化(重新切换内存映射) |
开销 | 较小 | 较大(切换页表等) |
CPU 寄存器 | 要保存 | 要保存 |
调度器参与 | 是 | 是 |
常见场景 | 多线程协作 | 多进程并发 |
三、线程切换时系统做了什么(关键步骤)
触发线程切换(中断/系统调用/调度)
常见触发场景:
- 时间片用尽
- 主动让出(
pthread_yield
/sleep
) - 阻塞(I/O、锁)
- 高优先级线程唤醒
陷入内核态
- 中断或系统调用进入内核态
- CPU 执行内核代码:线程调度器(Scheduler)
保存当前线程上下文
- CPU 寄存器(PC、SP、通用寄存器)
- 栈指针(线程私有)
- 调度器把这些状态保存到 TCB(Thread Control Block)
更新线程状态
- 当前线程标记为 READY / BLOCKED 等
- 目标线程标记为 RUNNING
选择下一个要运行的线程
- 调度策略(如时间片轮转、优先级调度、CFS)
- 找到最合适的线程
加载目标线程上下文
- 从 TCB 中恢复寄存器、PC、栈等状态
返回用户态执行新线程
- CPU 跳转到新线程的下一条指令
四、涉及的关键结构
结构体/概念 | 说明 |
---|---|
PCB/TCB | 进程控制块 / 线程控制块:保存上下文、状态等信息 |
CPU 寄存器 | 包括 PC、SP、通用寄存器 |
内核栈 | 每个线程有独立的内核栈 |
调度器(Scheduler) | 内核模块,用于选择哪个线程运行 |
五、可视化图解
[当前线程]
↓ 触发切换(时间片用尽)
↓ 保存上下文(寄存器 → TCB)
↓ 调度器选择下一个线程
↓ 恢复新线程上下文(TCB → 寄存器)
↓ CPU 开始执行新线程
六、性能开销
操作 | 说明 |
---|---|
用户态线程切换 | 开销较小(如协程) |
内核态线程切换 | 需陷入内核,性能开销大 |
进程切换 | 额外切换内存空间,开销更大 |
七、举例说明(Linux)
在 Linux 中,schedule()
是核心线程调度函数。
切换线程过程大致如下:
void context_switch(struct task_struct *prev, struct task_struct *next) {
// 保存 prev 的 CPU 上下文
switch_to(prev, next);
// 恢复 next 的上下文并运行
}
Linux 使用 task_struct
作为进程/线程控制块。
八、相关命令与工具
top
,htop
:查看线程状态perf
、strace
:分析切换频率与延迟vmstat
:查看上下文切换速率(字段cs
)
九、总结表
步骤 | 操作内容 |
---|---|
1. 触发切换 | 中断、系统调用、主动让出、阻塞 |
2. 保存上下文 | 保存寄存器、程序计数器、栈指针等 |
3. 调度线程 | 根据策略选中下一个线程 |
4. 恢复上下文 | 从 TCB 恢复 CPU 状态 |
5. 切换完成 | CPU 执行新线程 |