仅在中断期间读取变量时需要volatile

问题描述 投票:8回答:1

C标准规定,当变量的值有可能在程序的正常执行流程之外发生变化时,应该在变量的定义中使用volatile关键字。

如果在正常执行流程期间更改(写入)全局变量,并且仅在此正常流程之外读取(在中断中)。这个变量是否需要变化?为什么?

c embedded interrupt volatile
1个回答
5
投票

如果在正常执行流程期间更改(写入)全局变量,并且仅在此正常流程之外读取(在中断中)。这个变量是否需要变化?

是的,一点没错。

为什么?

确保正确执行中断处理程序(而不是正常流程)。


让我详细说明一下。

想象一下,你有一个像这样的变量:

int x;

您正在程序的正常流程中修改此变量,如下所示:

void modify(int *x){...some code here...}

在中断服务程序中,您正在读取变量。

请记住,中断可以异步(在任何时候)发生。还要记住,编译器会首先将您的代码转换为一系列机器指令,如下所示:

load val from mem to register
perform modification operations
store value from registers to memory
perform other operations where the variable is used

现在,编译器可以优化此程序以减少内存读写次数,如下所示:

load value
perform modifications
use value
...
modify register content
...
use
...
keep using value from the registers without ever storing in the memory.

在这种情况下,如果发生中断,(请注意,中断上下文通常与正常上下文不同,因此在许多架构中都有不同的寄存器集(比如arm ...)),它会尝试读取来自内存的变量值。但是由于编译器优化,内存的内容从未改变过。

因此,ISR可以读取一个旧值(更糟糕的是 - 我们不能确定一个值多大)会导致意外行为。

因此,应该将变量声明为volatile,以防止编译器干扰程序。

© www.soinside.com 2019 - 2024. All rights reserved.