在主程序和C中的ISR之间共享volatile变量是否安全?

在主程序和C中的ISR之间共享一个对齐的整数变量(不大于处理器自然字,使用volatile限定符)是否安全? 是否保证不会发生撕裂的读写操作?

volatile关键字并不意味着primefaces性 – 这只是确保显式读取变量而不是假设没有变化。 对于没有任何其他保护机制的安全共享访问,变量必须是primefaces的并且声明为volatile

编译器可以记录任何特定目标的primefaces类型,并且可以为此目的定义sig_atomic_t

通常,假设您的编译器不会执行任何反常操作并将指令集允许primefaces读取的对齐字读取分开也许是合理的。 但是,在平台之间移植代码时应该谨慎 – 这种低级代码应该被视为特定于目标且不可移植。

关于volatile关键字,它只是用来防止编译器可能出现的错误优化。 它对螺纹安全没有帮助。

使用给定大小的共享变量是否是线程安全的取决于编译器。 无法保证访问是primefaces的。 例如,编译器可能会在进一步处理之前将变量加载到寄存器中,然后将其写回内存。 主要取决于CPU指令集。 如果您想确定,则必须检查反汇编代码或在汇编程序中编写代码。

否则,你可以用一个布尔制作一个“穷人的互斥体”。 这仅适用于不能被其他中断中断的微控制器ISR的特定情况。 既然您知道ISR无法中断,您可以这样做:

 static volatile bool busy; static volatile uint16_t shared; void isr (void) { if(!busy) { shared = something; } } void main (void) { ... busy = true; do_something(shared); busy = false; ... } 

使用这种方法, busyshared是否是primefaces的并不重要。 无论中断在哪里触发, shared都不会在访问中被破坏。

无法保证任何通用整数变量将以primefaces方式写入和读取。 如果您需要这样的保证,您应该使用sig_atomic_t类型。 它是唯一具有这种保证的类型。

从C99标准7.14:

2定义的类型是

sig_atomic_t

即使在存在异步中断的情况下,也可以作为primefaces实体访问的对象的(可能是volatile限定的)整数类型。

检查你的编译器。 ISR是非标准的。 此外,C除了int之外没有“处理器自然词”的真实概念。

答案是“有时”。 如果ISR或主进程改变了变量,那么你就可以了。 但是,如果两者都操纵变量,就像

 main Var = Var + 10 ISR Var = Var + 10 

那谁知道呢? 你会认为最终的结果是var + 20,但如果在汇编中,序列就是

 Main - Get Var ISR - Get Var Add 10 Store Var Return Add 10 Store Var 

然后最终结果将是10,而不是20

正如之前的海报所说,你需要有一些保护代码来防止这种情况发生。