softirq 与tasklet:从irq_exit 到__do_softirq 的下半部路径

硬中断里只做「应答 + 调度下半部」,重活放到 softirq / tasklet / workqueue 。若把耗时逻辑塞进 hardirq,会出现关抢占过久、延迟尖刺、甚至 soft lockup。本文沿 irq_exit() → __do_softirq() 说明下半部何时跑、和 NAPI/定时器的关系,并给出可执行的绑核与观测手段。

源码锚点

路径 作用
kernel/softirq.c __do_softirq()、irq_exit 触发、open_softirq
include/linux/interrupt.h request_irq、tasklet、softirq 向量声明
kernel/irq/manage.c IRQ 申请与线程化中断
net/core/dev.c NET_RX_SOFTIRQ、NAPI 轮询
kernel/time/timer.c TIMER_SOFTIRQ
Documentation/core-api/irq/irq-domain.rst 等 中断子系统文档

软中断执行核心(概念):

c 复制代码
/* kernel/softirq.c */
asmlinkage __visible void __softirq_entry __do_softirq(void)
{
	unsigned long end = jiffies + MAX_SOFTIRQ_TIME;
	/* 按 pending mask 依次调用 softirq_vec[nr].action() */
}

注册与触发:

c 复制代码
open_softirq(NET_RX_SOFTIRQ, net_rx_action);
raise_softirq(NET_RX_SOFTIRQ);	/* 或 raise_softirq_irqoff */

调用链

text 复制代码
硬件 IRQ
  → 架构入口 → handle_irq_event
      → action->handler()          /* hardirq:短、不可睡 */
          → 常 raise_softirq / napi_schedule
  → irq_exit()
      → 若不在中断嵌套且有 pending softirq
          → invoke_softirq
              → __do_softirq()
                  → softirq_vec[i].action()
                      ├─ NET_RX_SOFTIRQ → net_rx_action → NAPI poll
                      ├─ TIMER_SOFTIRQ  → run_timer_softirq
                      ├─ TASKLET_SOFTIRQ → tasklet_action
                      └─ ...

若 softirq 跑太久 / ksoftirqd 接管:
  → wake ksoftirqd/<cpu>

驱动常用分层:

text 复制代码
request_irq(handler)
  handler: 清状态、读关键寄存器、napi_schedule / tasklet_schedule
  下半部: 组包、协议栈、耗时处理
更重或可能睡眠: queue_work(system_wq, ...)

重点知识

1. 为何要下半部

hardirq 期间通常关(或延迟)同线中断,逻辑越长,同设备与同 CPU 延迟越大。softirq 仍在软中断上下文(不可睡眠),但可批量、可延期到 ksoftirqd。

2. softirq vs tasklet vs workqueue

机制 可睡眠 典型用途
softirq 否 网络 RX/TX、timer、block 等高频
tasklet 否 驱动轻量延后(同 CPU 串行化语义)
workqueue 是 可能阻塞的收尾、与用户态交互

新代码更常见 threaded IRQ (request_threaded_irq)或 NAPI,而不是手写 tasklet。

3. 中断亲和与多队列

bash 复制代码
# IRQ 绑核
cat /proc/interrupts
echo <mask> > /proc/irq/<n>/smp_affinity
# 网卡多队列 + XPS/RPS(按需)
ls /sys/class/net/eth0/queues/

IRQ 全堆 CPU0 时,同核 softirq 也会挤在一起,表现为单核 100%、其它核空闲。

4. 时间与观测

bash 复制代码
cat /proc/softirqs
watch -n1 cat /proc/softirqs
perf top -e irq:softirq_entry
# 延迟
cyclictest -p 90 -i 1000 -l 10000   # 实时评估环境

5. 设计意图与踩坑

  • 意图:硬中断极短,吞吐型工作在 softirq/NAPI 批处理。
  • 坑 :在 hardirq 里 mutex_lock / 打印刷屏。
  • 坑:softirq 里睡------直接 BUG。
  • 坑 :忽略 ksoftirqd 占满,只盯硬中断计数。
  • 坑 :时间相关逻辑用可回拨的 wall clock;超时用 CLOCK_MONOTONIC。

Checklist

  • hardirq handler 只做应答与调度下半部,无睡眠 API
  • 能指出 irq_exit → __do_softirq 的触发条件
  • 按场景选 softirq / threaded IRQ / workqueue
  • 用 /proc/interrupts 与 /proc/softirqs 确认未单核打满
  • 高 PPS 网卡检查 NAPI 与中断聚合(coalescing)
  • 延迟敏感线程验证未与重 softirq 同核恶性争抢
相关推荐
codists10 小时前
《crafting interpreters》阅读笔记:p45-p45
python
曲径海盗11 小时前
【Python 学习第 41 天】for 循环
python·学习笔记·编程入门
摇滚侠11 小时前
《On Java 中文版 基础卷》阅读笔记 实现隐藏 11
java·笔记·python
沧海一笑-dj12 小时前
【Python】Python学习笔记-模块与包
python·pip·模块·包·python包·python模块·包与模块
echome88812 小时前
Python 异常处理:try、else、finally 的正确搭配
开发语言·前端·python·异常处理·编程技巧
云和数据.ChenGuang12 小时前
Python 单继承与多继承深度剖析:从 MRO 到实战取舍
开发语言·人工智能·python·langchain
威哥爱编程12 小时前
Python 智能体开发实战 02:你的 AI 助教说话像换了个模型?九成的 system prompt 都写错了
python·agent
威哥爱编程12 小时前
Python 智能体开发实战 01:装了三遍环境还在报错?虚拟环境和 DeepSeek 一次配到位
python·agent
小咕聊编程12 小时前
基于Python的豆瓣电影数据可视化系统构建分析
开发语言·python·信息可视化
小小张说故事14 小时前
Python 的 dict 为什么查询是 O(1)?拆开哈希表、扰动函数与扩容阈值
python