当前位置:首页>Linux>Linux中断下半部:优先级排序+指定类型调用接口全梳理

Linux中断下半部:优先级排序+指定类型调用接口全梳理

  • 2026-10-10 16:35:38
Linux中断下半部:优先级排序+指定类型调用接口全梳理

一、中断下半部类型及优先级(从高到低)

中断下半部共分三大类,优先级严格递减,且软中断内部有内核固定优先级分级,具体划分如下:

1. 软中断(softirq)

下半部中最高优先级,运行在中断上下文,不可休眠、执行速度快,内核静态定义固定类型,内部优先级从高到低依次为:

HI_SOFTIRQ(高优先级tasklet)→ TIMER_SOFTIRQ(时钟软中断)→ NET_TX_SOFTIRQ(网络发送)→ NET_RX_SOFTIRQ(网络接收)→ BLOCK_SOFTIRQ(块设备)→ IRQ_POLL_SOLLIRQ → TASKLET_SOFTIRQ(普通tasklet)→ SCHED_SOFTIRQ(进程调度)→ HRTIMER_SOFTIRQ(高精度定时器)→ RCU_SOFTIRQ(RCU资源回收)

2. tasklet

基于软中断实现,依托 HI_SOFTIRQ 和 TASKLET_SOFTIRQ 两种软中断,优先级与所属软中断完全一致;同样运行在中断上下文,不可休眠,使用比软中断更简单,支持动态注册,是驱动开发常用下半部方案。

3. 工作队列(workqueue)

下半部最低优先级,运行在内核线程上下文,允许休眠(可调用mutex、内存分配等阻塞接口),适合处理耗时、可阻塞的下半部逻辑,对系统实时性影响最小。

二、指定中断下半部类型的内核调用接口

在驱动开发中,硬件中断上半部处理完成后,可通过对应内核API,指定该中断的下半部为软中断/tasklet/工作队列,具体接口及使用逻辑如下:

(一)指定下半部为软中断(softirq)

软中断为内核静态分配,驱动极少自定义,多用于网络、块设备等核心模块,核心接口:

open_softirq(int nr, 

   void (*action)(struct softirq_action *)) 

- 作用:注册指定类型的软中断处理函数

- 参数: nr 为软中断类型(如NET_RX_SOFTIRQ), action 为下半部处理函数

raise_softirq(int nr) 

- 作用:中断上半部中调用,触发对应软中断,标记其挂起待执行

- 示例:上半部执行完,调用 raise_softirq(NET_RX_SOFTIRQ) ,指定网卡中断下半部为网络接收软中断

(二)指定下半部为tasklet

驱动开发最常用,接口简单、无需关注软中断底层,核心接口:

DECLARE_TASKLET(name, func, data) 

- 作用:静态定义tasklet结构体,绑定处理函数

tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long), unsigned long data) 

- 作用:动态初始化tasklet

tasklet_schedule(struct tasklet_struct *t) 

- 作用:中断上半部中调用,调度tasklet执行,将其加入对应软中断链表

- 示例:上半部硬件处理完成后,调用 tasklet_schedule(&my_tasklet) ,指定该中断下半部为tasklet

(三)指定下半部为工作队列(workqueue)

适合可休眠、耗时场景,分共享工作队列和自定义工作队列,核心接口:

1. 共享工作队列(简单易用,无需创建队列)

DECLARE_WORK(name, func) :静态定义工作项

INIT_WORK(struct work_struct *work, void (*func)(struct work_struct *work)) :动态初始化工作项

schedule_work(struct work_struct *work) :中断上半部中调用,调度工作项到共享队列执行

2. 自定义工作队列(避免共享队列阻塞)

create_workqueue(const char *name) :创建自定义工作队列

queue_work(struct workqueue_struct *wq, struct work_struct *work) :调度工作项到自定义队列

- 示例:上半部完成后,调用 schedule_work(&my_work) ,指定中断下半部为工作队列

三、关键补充规则

1. 所有下半部必须等所有中断上半部(含嵌套的高优先级上半部)执行完毕,才会按优先级调度执行;

2. 软中断、tasklet不可休眠,工作队列可休眠;

3. 下半部执行时可被新的硬件中断(上半部)打断,不会互相抢占;

4. 同一优先级软中断/tasklet,会遍历链表执行完所有挂起任务,才会退出下半部流程。

关注我,每天进步积累一点点,谢谢您!

最新文章

随机文章