是否需要通过访问功能访问共享内存?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (17)

在查看嵌入式系统代码时,我看到的最常见的错误之一是忽略了线程/中断共享数据的易失性。然而,我的问题是,不使用是否“安全”?volatile当通过访问函数或成员函数访问变量时?

在下面的代码中:

volatile bool flag = false ;
void ThreadA()
{
    ...
    while (!flag)
    {
        // Wait
    }
    ...
}

interrupt void InterruptB()
{
    flag = true ;
} 

变量flag必须是易失性的,以确保线程A中的读取不被优化,但是如果标志是通过函数读取的

volatile bool flag = false ;
bool ReadFlag() { return flag }
void ThreadA()
{
    ...
    while ( !ReadFlag() )
    {
        // Wait
    }
    ...
}

真的flag还需要动荡不安吗?我知道这是不稳定的,但我担心的是,当它被省略,而不被发现时,这是否安全?

上面的示例非常简单;在实际情况中,我有一个类库包装了RTOS,这样就有一个抽象类cTask,任务对象是从它派生出来的。这样的“活动”对象通常具有访问数据的成员函数,而不是在对象的任务上下文中被修改,而是从其他上下文中访问数据;那么,这样的数据被声明为易失性是否很重要呢?

提问于
用户回答回答于

我对C99的解读是,除非你指定volatile,如何以及何时实际访问变量是定义的实现。如果指定volatile限定符,那么代码必须按照抽象机

标准中的相关部分是:6.7.3 Type qualifiers(挥发性描述)和5.1.2.3 Program execution(抽象机器定义)。

易失性使编译器清楚地知道,对变量的每次访问实际上都应该是对内存的访问。如果没有易失性,编译器似乎可以不重读变量。

而BTW将访问包装在一个函数中不会改变这一点,因为一个函数即使没有inline编译器可能仍在当前编译单元中内联。

对于C++,可能值得检查前者所基于的C89。

用户回答回答于

就像你说的volatile防止共享内存上的代码中断优化[C++98 7.1.5p8]

由于永远不知道给定的编译器现在或将来会进行什么样的优化,所以应该显式地指定变量是易失性的。

扫码关注云+社区