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 同核恶性争抢
相关推荐
yi0113 分钟前
LeetCode 219:存在重复元素 II——哈希表记录“最近一次出现的位置”
数据结构·人工智能·笔记·python·算法·leetcode·哈希表
Marst Code1 小时前
上位机开发日记 · 第 2 篇 · 架构先行:六层分层与边界
python
李日华大战鸡红2 小时前
FOC状态空间方程模型推导(学习记录)
python·学习·线性代数
外收内放4 小时前
Python基础语法练习题(57-58)
开发语言·python
朝朝辞暮i5 小时前
VLA 系统学习第 3 课:从一次机器人示范,到真正送进神经网络的 Batch
人工智能·python·深度学习·神经网络·vla
小鹿的周先生5 小时前
第11章-Structured-Output
开发语言·人工智能·python
梦在远山后5 小时前
通过 WSS 让 Server 安全调用 Desktop 本地工具(下01):Ticket、人工确认、幂等与断线对账
python·langchain·agent
泡海椒5 小时前
JQuick-Excel 实战:FORMAT 管理日期与数字的 Excel 显示
开发语言·python·excel
学掌门7 小时前
老司机带你十分钟入门Python!
开发语言·python
YEGE学AI算法7 小时前
Python实现Log-Mel Fbank:分帧、加窗、FFT与Mel滤波器组
python·语音识别·fbank·log-mel·音频特征