中断与下半部机制

本文对应 成长路径 高优先级:在驱动中 缩短硬中断,按场景选择 tasklet / workqueue / threaded IRQ


学习目标

  • 区分 上半部(硬中断)下半部 的职责。
  • 使用选用表决定 tasklet / workqueue / kthread
  • 能阅读 /proc/interruptsIRQ affinity

选用表

机制上下文可睡眠典型场景
硬中断 top half中断清中断源、读 FIFO 指针、调度下半部
tasklet软中断短、非重入敏感逻辑(旧代码常见)
workqueue进程I2C 传输、分配内存、用户通知
threaded IRQ内核线程新驱动推荐,上半部极短
kthread进程轮询、复杂状态机

原则:硬中断里只做必须快的;其余延后。


硬中断示例(概念)

static irqreturn_t my_irq(int irq, void *dev_id)
{
    /* 读状态寄存器、ack 中断 */
    tasklet_schedule(&priv->t);
    return IRQ_HANDLED;
}

避免:printkmutex_lockmdelay


tasklet

static void my_tasklet(struct tasklet_struct *t)
{
    struct my_dev *priv = from_tasklet(priv, t, t);
    /* 仍不可睡眠 */
}

同一 tasklet 不会并行 执行,但可与其他 tasklet 并发。


workqueue

schedule_work(&priv->work);
/* work_fn 中可 mutex、kmalloc(GFP_KERNEL) */

系统 workqueue 与 WQ_MEM_RECLAIM 等专用队列按负载选择。


threaded IRQ(推荐)

request_threaded_irq(irq, hard_handler, thread_fn, flags, name, dev);
  • hard_handlerIRQ_WAKE_THREAD 唤醒线程。
  • thread_fn:可睡眠,适合 SPI/I2C 等慢总线。

与同步的关系

硬中断与进程上下文争用同一数据时,需 spinlock_irqsaveRCU,见 内核同步机制总览


实践清单

  • 统计某网卡 IRQ 在 /proc/interrupts 的增长速率
  • 将 demo 驱动中的 mdelay 从中断处理移到 workqueue
  • 对比 threaded IRQtasklet 的 latency(示波器或 trace_irqsoff

延伸阅读