【1112】Linux中断【整理】

Linux中断

Linux中断:上半部 & 下半部

核心目的:上半部快进快出,避免长时间关中断、丢中断;耗时工作延后交给下半部

下半部不是必须,只有需要延后处理的时候才用。

优先级分层

  1. 最高:硬件中断(上半部)
    外设触发,进入中断服务函数。
    特点:
  • 中断上下文,不能休眠
  • 只做紧急活:清中断标志、接收简单数据、标记事件、调度下半部
  • 上半部之间是平级,先到先得,高优先级硬件中断可以抢占低优先级
  1. 第二:下半部
    两类:tasklet、workqueue
  • tasklet(基于softirq软中断)
    中断上下文,没有PCB,没有进程栈,禁止休眠 ;优先级高于workqueue。
    适合短时、不阻塞的延后任务。
    风险:中断频繁爆发时,tasklet一直抢占,会把普通进程饿死(典型:网络收包)。
  • workqueue(工作队列)
    进程上下文,依托内核线程,有PCB、独立进程栈,允许休眠、阻塞、等待 。
    适合耗时、需要等待的任务;优先级低于tasklet。
  1. 第三:ksoftirqd 内核线程(兜底方案)

    softirq触发太频繁(反复触发超过阈值),不能一直卡在中断上下文,内核交给ksoftirqd内核线程去跑软中断,防止其他进程被饿死。

  2. 普通用户/内核进程

    时间片轮转调度。

中断上下文 vs 进程上下文(面试背诵版)

对比项 中断上下文(上半部、softirq、tasklet) 进程上下文(workqueue、ksoftirqd、普通进程)
归属 不属于任何进程,没有task_struct(PCB) 属于一个task,有独立PCB、进程描述符
栈 临时借用被打断进程的栈,没有专属栈 拥有自己独立进程栈
调度方式 不走调度器,中断返回前顺路执行;没有时间片 由调度器schedule()管理,时间片轮转、唤醒运行
能否休眠 ❌ 禁止休眠、阻塞、等待锁 ✅ 可以休眠、等待IO、等待互斥锁
抢占关系 优先级更高,可以抢占进程上下文任务 不能抢占中断上下文,来了中断就被打断
触发来源 硬件外设触发中断 内核主动唤醒、调度挑选
典型场景 清中断标志、简单数据搬运、标记软中断 读Flash、内存分配、等待信号、耗时业务

下文切换

一、中断上下文切换(硬件打断,不是进程切换!重点)

它是「打断正在跑的进程,临时进中断」,不会调用schedule()

流程:

  1. CPU正在运行某个进程(进程上下文)
  2. 外设发来中断信号 → CPU硬件自动动作:
    • 保存当前现场(通用寄存器、程序计数器)到被打断进程的栈
    • 跳转到中断向量表,进入内核中断入口
  3. 进入中断上下文(上半部 → 可能接着跑softirq/tasklet)
  4. 中断处理完毕,准备返回:
    • 检查有没有pending软中断,有就执行
    • 恢复之前保存的寄存器现场
    • 回到刚才被打断的进程,继续跑

✅ 关键点:

没有换PCB,没有换栈,只是临时借栈跑一段代码,不是进程切换。

二、进程上下文切换(进程之间切换,调用schedule())

从一个task切到另一个task,是调度器主导

流程:

  1. 当前进程主动放弃CPU(休眠、时间片到、被抢占)
  2. 保存当前进程的全部现场(寄存器)到自己的PCB + 自己的进程栈
  3. 调度器挑选下一个就绪进程
  4. 拿到新进程的PCB,恢复它的寄存器、栈
  5. 跳转到新进程代码执行

✅ 关键点:更换PCB、更换独立进程栈

Linux内核时间把控 精简总结

源头:时钟中断,晶振产生周期性脉冲,是内核所有时间体系的基础。

  1. 忙等待(短延时,占用CPU)
    udelay / mdelay:循环空转、消耗CPU,适合极短延时,CPU全程不释放。
  2. jiffies滴答计数
    时钟中断触发计数,搭配 time_before / time_after 做时间对比判断,用来轮询等待超时。
  3. 内核定时器 timer_list
    设置expires到期值,到期自动回调function函数,属于异步定时。
  4. 调度睡眠(长延时,释放CPU)
  • schedule():主动让出CPU,何时恢复由调度器决定,无固定超时
  • schedule_timeout() / msleep():让出CPU,超时后自动唤醒
  • schedule_timeout_interruptible():睡眠期间可以被信号打断

✅ 选型口诀:

短延时用 udelay/mdelay(忙等);

长等待优先睡眠调度,避免CPU空耗;

需要定时触发动作用timer_list;

需要轮询判断超时用jiffies比较。

中断禁用(屏蔽)

bash 复制代码
local_irq_disable() //禁用本地中断的传递
                    //local_irq_enable   恢复本地中断的传递
local_irq_save(flags) //保存当前中断状态后,再禁用本地中断的传递 -> 比local_irq_disable更安全
                     //local_irq_restore(flags) 恢复本地中断的传递到指定状态

disable_irq(irq_num); //禁用指定中断
                     //enable_irq(irq_num)  使能指定中断  
 
//注: 屏蔽中断的时间尽量短,否则会造成别的中断延时过久,甚至丢失,最好能采有屏蔽指定中断的方式  
相关推荐
分布式存储与RustFS18 分钟前
OpenObserve 的日志别堆本地盘:用 RustFS 当它的对象存储底座
运维·云原生·开源·对象存储·分布式存储·s3·性能基准
CodeYp20192 小时前
第14讲:传输层协议 UDP
linux·udp
北京迅为2 小时前
案例分享 | RK182X算力卡:多路视频VLM监控,四路画面AI同时看懂,一句人话说清现场
linux·人工智能·嵌入式·rk3588·算力卡·rk182x
新*2 小时前
ES 7.17 三节点 Docker 集群接入 IK 自定义词典:一次从丢插件到热更新的完整排障
运维·elasticsearch·docker·中文分词·ik分词
风翼靓崽2 小时前
jenkins搭建与简单使用
运维·jenkins
lzx_00214 小时前
Linux 进程(三) 从进程状态到僵尸进程、孤儿进程
linux·服务器
FlightYe15 小时前
音视频修炼之容器与协议(四):RTSP详解
android·linux·ffmpeg·音视频·dash
刘马想放假16 小时前
CANviz 使用指南|Linux 安装、DBC 解码、实时曲线与 J1939 实战
linux·python·websocket
kloc17 小时前
聊天室项目入口网关子服务的实现
linux·c++