当前位置:首页>Linux>Linux 中断:上半部(top half)、下半部(bottom half)

Linux 中断:上半部(top half)、下半部(bottom half)

  • 2026-10-11 05:43:23
Linux 中断:上半部(top half)、下半部(bottom half)

------AI创作------

一、核心背景:中断处理的矛盾

硬件中断触发时,CPU 立刻停下当前程序去处理设备,但有两个约束:

  1. 中断上下文环境限制:不能睡眠、不能阻塞、不能长时间循环;
  2. 中断屏蔽:处理当前中断时,同级别硬件中断会被屏蔽,处理越久,其他硬件越容易丢失中断。

解决方案:拆分工作,分成两段执行

  • 上半部:紧急、必须立刻硬件应答的少量工作(原子、快、禁止睡眠)
  • 下半部:耗时、复杂、可以延后处理的工作(允许调度、耗时操作)

二、上半部 Top Half(中断服务程序 ISR)

职责(只做必须马上干的事)

  1. 读取硬件寄存器,清除中断标志(否则硬件会反复发中断);
  2. 把关键数据从硬件缓冲区拷贝到内存;
  3. 触发下半部,延后处理剩余复杂逻辑;

特点

  1. 运行在中断上下文,无进程、不能 sleep()、不能互斥锁睡眠;
  2. 执行时间极短,微秒级;
  3. 执行期间会屏蔽同类型硬件中断;
irqreturn_tdev_isr(int irq, void *dev_id){    // 1. 清硬件中断标志    read_reg();    // 2. 拷贝少量硬件数据    // 3. 触发下半部延后处理    tasklet_schedule(&dev->tasklet);    return IRQ_HANDLED;}

三、下半部 Bottom Half(延后执行)

职责(所有耗时工作丢这里)

数据包解析、内存拷贝、协议处理、日志上报、大量循环、加锁等待等;

特点

  1. 依然不属于普通进程上下文,但允许调度让出 CPU,不会长时间阻塞硬件中断;
  2. 可以执行复杂逻辑,毫秒甚至百毫秒级;
  3. 不会长期屏蔽其他硬件中断;

四、Linux 四种下半部实现机制(演进顺序)

1. tasklet(最常用,简单设备驱动首选)

  • 基于软中断,同一种 tasklet 不会并行执行;
  • 适合字符设备、简单外设(按键、传感器);
  • API:tasklet_init / tasklet_schedule

2. 软中断 softirq(底层、高性能)

  • 多核可并发运行,性能高;
  • 仅内核网络、块设备子系统使用,驱动开发者很少直接用;例:网络收包、磁盘 IO 完成处理。

3. workqueue 工作队列(唯一能睡眠的下半部)

  • 运行在进程上下文,可以睡眠、等待信号量;
  • 中断里有耗时阻塞操作必须用 workqueue;API:INIT_WORK / schedule_work

4. 旧机制:bh(废弃,2.6 内核后彻底移除)

早期下半部,性能差,现已淘汰。

五、举个通俗例子:网卡中断

上半部(ISR,立刻执行)

  1. 通知网卡停止发中断;
  2. 把硬件 FIFO 里少量数据包拷贝到内核缓冲区;
  3. 触发软中断(下半部);耗时几微秒,快速退出,放开硬件中断

下半部(softirq 软中断)

  1. 完整解析以太网头、IP、TCP;
  2. 校验和、分片重组;
  3. 把数据递交给用户态 socket;耗时更长,但不会阻塞其他网卡中断
维度
上半部 Top Half
下半部 Bottom Half
运行上下文
中断上下文
软中断 / 工作队列上下文
能否 sleep
绝对不能
workqueue 可以 sleep,tasklet/softirq 不行
屏蔽中断
执行时屏蔽同级硬件中断
不屏蔽硬件中断,其他设备可正常中断
执行时长
极短(微秒)
允许较长(毫秒)
核心任务
硬件应答、快速取数据
复杂业务逻辑、数据处理

七、设计原则(写驱动必遵守)

  1. ISR(上半部)代码越少越好,绝不放循环、打印、复杂运算;
  2. 凡是耗时操作、内存分配、文件操作、阻塞等待,全部扔下半部;
  3. 需要睡眠 → workqueue;简单快速处理 → tasklet;高速吞吐设备 → softirq。

八、一句话总结

上半部快速响应硬件,避免丢中断;下半部延后处理脏活累活,保证系统响应速度。

最新文章

随机文章