CPU在当前指令执行完后立即暂停任务,硬件自动压入PC、CPSR/RIP/RFLAGS等寄存器到栈;随后经硬件向量跳转、中断控制器仲裁、内核asm_do_IRQ()三层调度才进入handler。

中断触发后,CPU 怎么第一时间“停下手头活”?
硬件中断信号(比如网卡收到包、键盘按键)到达 CPU 的 INTR 引脚后,CPU 在当前指令执行完的边界立即暂停用户态或内核态任务,自动压入 PC、CPSR(ARM)或 RIP/RFLAGS(x86_64)等关键寄存器到当前栈——这一步完全由硬件完成,不依赖内核代码。你写驱动时看不到它,但它是整个中断流程不可绕过的起点。
常见误区是以为“中断一来就跳进你的 irq_handler_t”,其实中间隔着至少三层:硬件向量跳转 → 中断控制器(如 GIC 或 APIC)仲裁 → 内核通用入口 asm_do_IRQ()。如果你在 /proc/interrupts 里看到某 IRQ 计数不动,大概率是硬件没发信号,或者中断控制器配置漏了使能位(比如 GICD_CTLR 寄存器没置位)。
request_irq() 注册的是顶半部,但它到底干了什么?
调用 request_irq() 不是把函数直接塞进硬件,而是把你的处理函数挂到对应 irq_desc[irq] 结构体的 action 链表上,并让内核在该 IRQ 触发时调用 handle_irq() —— 这个函数再遍历 action 链表,逐个执行注册的 handler。所以多个驱动可以共享一个 IRQ(如 PCI 设备),只要每个 handler 开头都检查自己设备的中断状态寄存器是否真被触发。
- 必须用
IRQF_SHARED标志才能和别人共用 IRQ,否则request_irq()直接失败 - handler 函数运行在中断上下文,不能调用
sleep()、copy_to_user()、mutex_lock()等可能阻塞的函数 - 返回值只能是
IRQ_NONE(不是我的中断)、IRQ_HANDLED(我处理了)、IRQ_WAKE_THREAD(交给线程化底半部)
为什么 ISR 里不能做耗时操作?底半部怎么选?
顶半部执行时,同 IRQ 会被自动屏蔽(disable_irq_nosync() 效果),如果在里面解析完整 TCP 包、写磁盘、分配大内存,其他设备(比如鼠标、定时器)就会卡住——你拖动窗口延迟、音频断续,根源可能就在这几行代码里。
2088shop商城购物系统是商城系统中功能最全的一个版本:非会员购物、商品无限级分类、不限商品数量、商品多级会员定价、上货库存、Word在线编辑器、订单详情销售报表、商品评论、留言簿、管理员多级别、VIP积分、会员注册积分奖励、智能新闻发布、滚动公告、投票调查、背景图片颜色更换、店标上传、版权联系方式修改、背景音乐(好歌不断)、广告图片支持Flash、弹出浮动广告、搜索引擎关健词优化、图文友情联
Linux 提供三类底半部机制,选错会影响实时性或吞吐:
-
softirq:内核编译时静态分配,高优先级、无锁、可重入,适合网络协议栈(NET_TX_SOFTIRQ)等极致性能场景,但必须用open_softirq()预注册,驱动一般不用 -
tasklet:基于 softirq 封装,单 CPU 串行执行,简单安全,适合大多数驱动(如 USB 主机控制器),但已标记为 legacy,新驱动建议避开 - 线程化中断(
IRQF_ONESHOT | IRQF_TRIGGER_*+request_threaded_irq()):把耗时部分放进内核线程,可调度、可睡眠、可使用全部内核 API,现代驱动首选
/proc/interrupts 和 cat /sys/firmware/devicetree/base/interrupt-controller@.../interrupts 对不上怎么办?
这是嵌入式开发最常踩的坑:设备树里写的 interrupts = ,对应的是 GIC SPI 中断号 23,但 /proc/interrupts 显示的是 Linux 全局 IRQ 编号(通常是 GIC 基地址 + 23)。如果你用 request_irq(23, ...) 肯定失败——得查 gic_irq_domain_translate() 或直接看启动日志里 “GICv2: using LPIs, GICD_BASE=0x...” 后推算,或者更稳妥:用 platform_get_irq() 从设备结构体里取,它已帮你做了映射。
另一个隐藏陷阱:某些 SoC(如 i.MX6ULL)的 GPIO 中断需要先调用 gpio_to_irq() 转换,而这个转换依赖 pin controller driver 是否已 probe 完成——如果驱动 initcall 顺序不对,gpio_to_irq() 可能返回 -EINVAL。









