字节跳动BSP面试 -- Linux 嵌套中断处理
前言
- 面试字节跳动 BSP 岗时问到在内核态出现嵌套时应该怎么处理。当时我的回答是 Linux 不支持中断嵌套。
- 理论上我说的并没有错,但是当前场景是面试,不是问答。所以对方应该希望看到我回答的深度,而不是对不对。后续面试官问还有吗(这里感觉面试官在尝试提醒),我就说没了,哎,有点对自己失望了。
- 这里记录一下面试场景下正确的回答,如果有补充,欢迎大佬留言。
- 个人邮箱:zhangyixu02@gmail.com
正文
上半部
- 在 Linux 驱动开发中,内核将会自行处理中断嵌套问题,作为开发者只需要遵循 Linux 规定的框架,上半部尽可能简短,任务推向下半部处理。
- Linux 在处理中断时,会禁用本地 CPU 中断,防止出现同一 CPU 中断嵌套现象。如果是多核系统,那么新中断会路由到空闲 CPU,确保同一 CPU 同一时间只处理一个中断,避免中断嵌套现象。
- 如果出现新中断,但没有空闲 CPU。那么中断控制器将会管理状态机。
- 当没有中断时,中断控制器处于 Inactive 状态。
- 当出现一个中断时,那么将会进入 pending 状态等待 CPU 来处理。
- 当该中断被某个 CPU 选中并执行,那么此时进入 Active 状态。
- 在处理第一个中断时,又出现了第二个中断。GIC 中断控制器会将第二个中断设置为 Active and pending。
- 虽然 Linux 不支持中断嵌套,但是在 GIC 中断控制器中存在抢占机制。在 CPU 处理第一个中断时,出现了两个中断,那么优先级高的中断将在 CPU 处理完第一个中断后优先执行。(类似 CAN 仲裁机制)

- 下图是 ARM 官方手册,对于中断处理嵌套处理机制时序图,感兴趣的自行分析。

下半部与上半部
- 如上情况都是对于中断上半部情况。存在一种情况,第一个中断处于中断下半部,此时来了一个相同中断情况。那么此时的中断下半部是可以被打断的。
- 因此可能存在下半部和上半部访问共享数据的情况,因此需要用 spin_lock_irqsave 和 spin_unlock_irqrestore 同步保护,该锁会禁用中断,防止临界区出现新中断也获取该锁,导致死锁。不过这样会导致新中断调用延迟,因此需要确保临界区足够短。
- 下半部在执行,出现一个相同的中断。而在中断上半部没有确认是否有下半部正在运行,那么将会出现下半部被反复调用,因此需要使用原子变量确认是否有下半部正在运行。
- 中断上半部与下半部是多对一的关系。因此存在下半部丢失情况,需要考虑丢失现象是否能够接受,如果不能接受可尝试利用某个变量记录上半段次数来确保下半部无丢失现象。
- 除此之外,可能还存在下半部被长时间打断,导致延迟严重。如果在下半部中存在一些需要响应的操作,会导致超时现象。
- 除了上面情况,可能还存在新中断导致中断被分发到其他 CPU 导致一些本地内存问题。(这些东西我没遇到过,也不太懂,查了一些资料,术语太多,看不明白。感兴趣的自行查阅资料)