一、处理器的三种运行状态
- 用户态,运行于用户空间
- 内核态,运行于进程上下文
- 内核态,运行于中断上下文
二、进程上下文(Process Context)
✅ 定义:
当进程运行时,CPU 寄存器、堆栈、程序计数器、任务状态段等构成其运行状态。这些状态的集合称为“进程上下文”。
进程上下文是内核代表某个进程在内核空间中执行系统调用或异常处理的状态。
🔍 上下文结构:
- 用户级上下文:正文段、数据段、用户栈、共享存储区等;
- 寄存器上下文:SP(栈指针)、IP(指令指针)、FLAGS、通用寄存器;
- 系统级上下文:进程控制块(task_struct)、内核栈、内存管理结构(mm_struct等);
🧩 划分:
- 进程上文:从用户态进入内核态前需要保存的用户态寄存器、堆栈等内容;
- 进程下文:切换到内核态后执行的系统调用或异常处理等内核代码。
💡 作用:
- 允许内核获取/处理进程请求;
- 支持系统调用、页错误、软中断等场景;
- 保证执行系统调用后能恢复到用户态继续执行。
三、中断上下文(Interrupt Context)
✅ 定义:
中断上下文是内核为了响应外设等硬件事件,在被打断的进程或线程上下文中临时执行中断服务程序(ISR)的运行环境。
内核不是代表某个进程运行,而是代表硬件中断事件运行。
🧩 划分:
- 中断上文:硬件中断打断当前CPU执行状态,保存CPU寄存器、程序计数器、堆栈指针等,称为“中断现场”;
- 中断下文:保存完上文后,CPU跳转执行 ISR,即中断处理程序。
💡 特点:
- 不能睡眠、不能阻塞;
- 没有当前进程(
current
有值但不能使用如 schedule 等操作); - 不能访问用户空间;
- 不可抢占(直到处理完);
- 不允许持有自旋锁时间过长;
- 不能执行系统调用等需要进程支持的操作。
四、进程上下文 vs 中断上下文
项目 | 进程上下文 | 中断上下文 |
---|---|---|
触发方式 | 系统调用、异常 | 硬件中断 |
是否关联进程 | 是 | 否 |
是否可睡眠/阻塞 | ✅ 可以 | ❌ 不可以 |
是否可访问用户空间 | ✅ 可以 | ❌ 不可以 |
是否可以抢占 | ✅ 可以 | ❌ 不可以(除非开启抢占) |
是否可以调度 | ✅ 可以 | ❌ 不可以 |
是否可以调用调度器 | ✅(如 schedule) | ❌(否则死锁) |
五、中断现场保护(CPU上下文保存)
✅ 定义:
中断发生时,CPU 要保存当前执行状态(称为“中断现场”),以便中断服务结束后,能够正确返回原来的执行现场。
🎯 需要保护的内容:
- 通用寄存器(如:AX, BX, CX, DX…):这些寄存器在程序中用来临时存储数据、运算结果或中间值
- 程序计数器(IP):指向即将执行的下一条指令地址。每执行完一条指令,IP 自动加上指令长度
- 标志寄存器(FLAGS):包含系统状态和控制标志位,如零标志ZF、进位标志CF、中断允许标志IF 等
- 堆栈指针(SP):指向当前栈顶,用于管理函数调用、返回、局部变量等
- 段寄存器(如:CS, DS, SS):这些寄存器用于段式内存管理,指定不同类型的内存段:
- 处理器状态(特权级、控制寄存器等): 这些不属于每次中断都需要保存的寄存器,但涉及特权模式切换、虚拟内存时会用到。
📌 现场保存方式:
- CPU 硬件自动压栈部分关键寄存器;
- 编译器生成汇编代码时保存更多寄存器;
- 汇编级 ISR 开头(如
SAVE_ALL
宏)手动压栈全部寄存器; - 返回前用
IRET
指令恢复。
六、中断代码中的注意事项
-
不能调用可能睡眠的函数
- 如
kmalloc(GFP_KERNEL)
、copy_from_user()
、mutex_lock()
等;
- 如
-
不能使用阻塞等待
- 如
wait_event()
等会导致调度;
- 如
-
不能访问用户空间地址
- 因为当前没有用户上下文;
-
不可执行系统调用
- 因为系统调用依赖于用户进程环境;
-
尽可能快,尽早退出
- 不可长时间占用 CPU,应快速处理或使用“中断下半部”机制(软中断、tasklet、工作队列等);
七、模式切换与上下文切换
类型 | 定义 | 举例 | 代价 |
---|---|---|---|
模式切换(Mode Switch) | 用户态 <–> 内核态 | 系统调用、异常 | 相对较轻,保存寄存器+堆栈 |
上下文切换(Context Switch) | 进程A <–> 进程B | 进程调度 | 成本高,需保存和恢复PCB、内存映射、内核栈等 |
八、状态切换时机总结
触发条件 | 切换类型 | 描述 |
---|---|---|
用户调用系统调用 | 用户态 -> 内核态 | 进程上下文 |
进程主动 sleep 或 I/O 阻塞 | 进程上下文切换 | context switch |
硬件产生中断 | 任意上下文 -> 中断上下文 | 中断上下文,保存中断现场 |
中断服务程序执行完 | 中断上下文 -> 原上下文 | 恢复中断前上下文 |
时钟中断触发调度 | 中断中切换进程 | context switch 由时钟中断调度 |
九、中断上下文 和 中断现场保护 的关系
✅ 中断上下文 是一种 CPU 执行状态,
🛡️ 中断现场保护 是为了进入这种状态而进行的“环境保存操作”。
📌 它们之间的关系概括如下:
关系维度 | 中断上下文 | 中断现场保护 |
---|---|---|
🧠 概念 | 内核因中断信号被打断,代表硬件设备事件执行代码的状态 | 中断发生时,为了保存被打断任务的执行环境而进行的操作 |
🎯 目的 | 处理外部中断请求 | 确保中断处理后能正确返回原任务 |
🛠️ 内容 | CPU 执行中断服务程序(ISR)期间的运行状态(非进程上下文) | 保存 CPU 各类寄存器、程序计数器、标志位、栈指针等 |
📌 触发 | 中断控制器发送中断信号后,CPU 响应进入中断服务 | 进入 ISR 之前自动+手动完成保护 |
🧩 关系 | 是一种运行状态 | 是进入该状态的“准备动作” |
🧵 类比 | 做手术时的“手术状态” | 为进入手术状态穿好手术服、洗手等“准备” |
🔁 过程示意:
- 中断触发(如外设请求)
- CPU 响应中断,打断当前执行流
- → 进行中断现场保护(保存当前寄存器、堆栈、状态)
- → 切换到中断上下文,执行 ISR(中断处理程序)
- ISR 执行完毕后 → 恢复中断现场
- → 返回原来的进程上下文或内核态执行流
🧠 举个例子理解:
比如你在写作业(进程上下文),这时妈妈叫你开门(外部中断):
- 🛡️ 你先把笔、纸、位置记录下来(= 中断现场保护)
- 🧠 然后你去开门(= 进入中断上下文)
- 🚪 开完门回来,重新拿起笔纸、回到原来页码(= 恢复中断现场,回到进程上下文)
内容 | 作用 |
---|---|
中断上下文 | 表示 CPU 处于处理中断的状态,是一种特殊内核态运行状态 |
中断现场保护 | 是进入中断上下文前必须做的保存动作,确保 ISR 执行完后能正确恢复原状态 |
关系 | 没有中断现场保护,就无法安全进入/退出中断上下文 |