17 同步与互斥(三) 中断屏蔽
1 简介
中断屏蔽是一种可以防止并发导致竞态的方法。
在进入临界区之前屏蔽系统中断可以保证正在执行的内核路径不被打断(进程调度也依赖于中断)。
不过在驱动编程中此方法并不值得推荐。因为驱动并不一定运行在单核上,面对SMP系统中断屏蔽并不能屏蔽掉别的CPU的中断操作,此时使用中断屏蔽也就不能实现我们预期的结果了。
2 常用API
-
local_irq_disable
禁止中断
#define local_irq_disable() do { raw_local_irq_disable(); } while (0)
-
local_irq_enable
使能中断
#define local_irq_enable() do { raw_local_irq_enable(); } while (0)
-
local_irq_save
- 禁止irq
- 保存irq禁止前的信息
#define local_irq_save(flags) \ do { \ raw_local_irq_save(flags); \ } while (0)
-
local_irq_restore
恢复之前保存的irq信息
#define local_irq_restore(flags) do { raw_local_irq_restore(flags); } while (0)
示例
unsigned long flags;
local_save_flags(flags);
...
local_irq_restore(flags);
3 基本原理
- 调用关系
local_irq_enable -> raw_local_irq_enable -> arch_local_irq_enable
local_irq_disable -> raw_local_irq_disable -> arch_local_irq_disable
-
实现
汇编指令 参数 说明 cpsid i 关中断 cpsie i 开中断 cpsid f 关异常 cpsie f 开异常 static inline void arch_local_irq_enable(void) { asm volatile( " cpsie i @ arch_local_irq_enable" : : : "memory", "cc"); } static inline void arch_local_irq_disable(void) { asm volatile( " cpsid i @ arch_local_irq_disable" : : : "memory", "cc"); }