1. 中断基础概念

大家好,我是老李。做嵌入式Linux开发这么多年,中断这个话题我几乎天天都在打交道。今天咱们就来聊聊中断的那些基础概念。别小看这些基础,我见过不少工程师在这上面栽跟头。

1.1 中断的定义

中断,说白了就是CPU正在干一件事,突然被另一件事打断,先处理完紧急的事,再回来继续干原来的活。

举个例子。你正在写代码,突然电话响了。你放下键盘接电话,接完再继续写。这就是中断。电话铃声就是中断信号,接电话就是中断处理程序。

在计算机里,中断是硬件通知CPU的一种机制。外设(比如网卡、键盘、定时器)通过中断告诉CPU:我有事找你,快来处理一下。

核心要点:中断是一种异步事件处理机制。CPU不需要一直轮询外设状态,外设主动通知CPU。

1.2 中断与轮询的区别

很多初学者会问:为什么非要用中断?轮询不行吗?

轮询就是CPU不停地问外设:你好了没?你好了没?你好了没?

中断是外设主动喊CPU:我好了,快来!

我做过一个项目,用轮询方式读取传感器数据。CPU占用率高达80%,系统几乎干不了别的。后来改成中断驱动,CPU占用率降到5%。差距就这么大。

对比项 中断 轮询
CPU利用率 高(只在需要时处理) 低(一直占用CPU)
响应延迟 快(毫秒级甚至微秒级) 取决于轮询间隔
实现复杂度 较高(需要配置中断控制器) 简单(循环读取状态)
适用场景 事件频率低、实时性要求高 事件频率高、实时性要求低

我的经验:如果外设事件频率超过每秒1000次,可以考虑用轮询或混合模式。中断太频繁反而会拖垮系统。

1.3 中断上下文

这个概念很重要。Linux内核把执行环境分成两种:进程上下文和中断上下文。

进程上下文:可以睡眠、可以调度、可以访问用户空间。说白了就是正常的代码执行环境。

中断上下文:不能睡眠、不能调度、不能访问用户空间。为什么?因为中断处理程序不是以进程为单位运行的,它没有进程控制块(PCB)。

我曾经犯过一个错误:在中断处理函数里调用了kmalloc(GFP_KERNEL)。这个函数可能会睡眠,结果系统直接死锁了。排查了整整两天才找到原因。

避坑指南:中断上下文里绝对不要调用可能睡眠的函数。比如:

  • kmalloc(GFP_KERNEL) → 应该用GFP_ATOMIC
  • mutex_lock() → 应该用spin_lock()
  • copy_from_user() → 这个根本不能用

中断上下文又分为上半部和下半部。上半部处理紧急的硬件操作,下半部处理耗时的逻辑。这个后面会详细讲。

1.4 中断号与中断向量

这两个概念容易混淆。我简单解释一下。

中断号:硬件给每个中断源分配的唯一编号。比如网卡的中断号是17,键盘是1。在Linux里,中断号是软件层面的概念,用int类型表示。

中断向量:CPU硬件层面的概念。它是一个地址表,每个表项指向一个中断处理程序的入口地址。x86架构的中断向量表有256个条目。

举个例子。你打电话给客服,先按1(中断号),然后系统根据1找到对应的客服人员(中断向量)。

在ARM架构里,中断向量表通常放在0x00000000或0xFFFF0000地址。Linux内核启动时会重新设置中断向量表。

// Linux内核中注册中断的典型代码
static irqreturn_t my_irq_handler(int irq, void *dev_id)
{
    // 处理中断
    printk("Interrupt %d occurred\n", irq);
    return IRQ_HANDLED;
}

// 注册中断
int ret = request_irq(IRQ_NUMBER, my_irq_handler, 
                      IRQF_TRIGGER_RISING, 
                      "my_device", dev_id);
if (ret) {
    printk("Failed to request IRQ %d\n", IRQ_NUMBER);
    return ret;
}

关键区别:

  • 中断号是软件标识,由内核管理
  • 中断向量是硬件机制,由CPU架构定义
  • Linux通过irq_desc数组管理所有中断号
  • 中断号到中断向量的映射由中断控制器完成

知识体系总览

下面这张图展示了中断基础概念的核心关系。我画了好几个版本,这个最清晰。

中断基础概念知识体系 中断系统 中断定义 异步事件处理机制,硬件通知CPU 中断 vs 轮询 CPU利用率高 vs 低 响应快 vs 取决于轮询间隔 中断上下文 不能睡眠、不能调度 上半部 + 下半部 中断号与中断向量 软件标识 vs 硬件机制 由内核管理 vs 由CPU架构定义 理解这些概念,是掌握中断子系统的第一步

嗯,以上就是中断基础概念的核心内容。我在实际项目中反复验证过这些知识点。记住一句话:中断是嵌入式系统的灵魂,理解中断就是理解系统如何响应外部世界。

个人建议:刚开始学中断时,不要急着看复杂的中断控制器驱动。先搞懂这几个基础概念,然后用一个简单的GPIO中断实验练手。我当年就是这么过来的。

专注资料整理