大家好,我是王鸽,之前写中断文章的时候,就感觉出现上下文这个词汇很频繁,这个是什么?有哪些分类?差别是什么?这是 Linux 内核里最经典、面试必考的一组概念,我给你用最清晰、最容易记住的方式讲透。
一句话:上下文 = 当前代码是在什么环境、什么时机、什么权限下被 CPU 执行的。对驱动来说,最关键就两类:
- 进程上下文
- 中断上下文
一、进程上下文 vs 中断上下文
1. 进程上下文(Process Context)
就是进程在内核里运行的状态。
- 是谁在跑:某个具体进程(有 task_struct)
- 可以休眠(schedule、mutex、wait_event、copy_from_user…)
- 可以休眠(
msleep、mutex、copy_from_user 等)
一句话记:进程上下文 = 可以睡觉、可以调度、有进程背景。
2. 中断上下文(Interrupt Context)
硬件触发中断 → 内核执行中断处理函数。
- 场景:硬件中断、IRQ handler、tasklet 等(来自硬件中断或软中断 /tasklet/work_struct(硬中断底半部))
- 绝对不能做的事
- 不能休眠(mutex、msleep、kmalloc(GFP_KERNEL)、copy_from_user…)
一句话记:中断上下文 = 不能睡觉、不能调度、必须快进快出。
| | |
|---|
| | |
| | 不可以 |
| | |
| | |
| | |
| | 必须很短 |
| mutex、semaphore、waitqueue | 自旋锁spinlock |
| | |
三、除了这两个,Linux 还有哪些「上下文」?
你问的这个非常关键,Linux 不止这两种。
1. softirq 上下文(软中断上下文)
2. tasklet 上下文
3. 原子上下文(Atomic Context)
这是一个统称:
只要是不能休眠、不能调度的,都叫原子上下文。
4. 内核线程上下文(Kernel Thread Context)
5. 用户上下文(User Context)
四、最简单的总结(背这个就够)
- 进程上下文
- 中断上下文
- 原子上下文所有不能睡眠的上下文统称(中断、softirq、tasklet、持自旋锁)。
- 其他:软中断上下文、tasklet 上下文、内核线程上下文、用户上下文。
Linux 内核驱动:判断当前上下文(可直接复制)
#include<linux/kernel.h>#include<linux/interrupt.h>#include<linux/preempt.h>#include<linux/sched.h>/* * 判断当前执行上下文 * 返回值: * 0 = 进程上下文 * 1 = 硬中断上下文 * 2 = 软中断/softirq/tasklet 上下文 */intget_current_context(void){ if (in_irq()) { /* 硬件中断上下文 */ return 1; } else if (in_softirq()) { /* 软中断、tasklet、timer 上下文 */ return 2; } else { /* 进程上下文(包括内核线程) */ return 0; }}EXPORT_SYMBOL(get_current_context);
常用判断宏(驱动里直接用)
in_irq()在硬中断上下文 → 返回非 0
in_softirq()在软中断 /tasklet/hrtimer → 返回非 0
in_interrupt()在任何中断类上下文(硬中断 + 软中断)→ 返回非 0等价:in_irq() || in_softirq()
in_atomic()在原子上下文(中断 + 持自旋锁 + 禁止抢占)→ 返回非 0
谢谢阅读点赞收藏!