以下是在运行Barrelfish操作系统时在Pandaboard上闪烁LED的一些代码.我的问题是,为什么不把LED的闪光灯,如果"挥发"关键字是从的定义中删除gpio_oe和gpio_dataout.
static volatile uint32_t *gpio_oe = (uint32_t *)(GPIO_BASE + 0x0134);
static volatile uint32_t *gpio_dataout = (uint32_t *)(GPIO_BASE + 0x013C);
void led_flash
{
// Enable output
*gpio_oe &= (~(1 << 8));
// Toggle LED on and off till eternity
while(true)
{
*gpio_dataout ^= (1 << 8); // Set means LED on; Clear means LED off
time_delay(); // To give blinking effect
}
}
Run Code Online (Sandbox Code Playgroud)
我知道如果变量的值可以通过程序外的源自发地改变,则需要使用volatile.但我在这里看不到这样的情况.编译器执行什么优化会使整个while循环闪烁LED无意义?这种优化背后的逻辑是什么,即.这种优化有意义的合法案例?
我目前正在课堂上学习C,而且我对易变变量有一些困惑.我的教科书将它们定义为此.
易失性变量
volatile变量是由其他外部程序或同一程序随时更改的变量.语法如下.
volatile int d;
正常变量和volatile变量之间究竟有什么区别?如果外部程序可以更改volatile变量,如何更改其他外部程序的值.
谢谢.
我正在尝试用C编写自己的小内核,实际上我想写一个print函数来显示字符串.因此,我想写入视频内存(0xB8000).
所以,我试过这样的:
unsigned char *video = (unsigned char *)0xB8000;
*video = 'A';
Run Code Online (Sandbox Code Playgroud)
这实际上有效,但以下不是:
char x = 0;
unsigned char *video = (unsigned char *)(0xB8000 + x);
*video = 'A';
Run Code Online (Sandbox Code Playgroud)
经过一些研究,我认为原因可能是编译器的优化,OSDev给我解决方案:使用volatile关键字.所以我对这个关键字做了一些研究.OSDev建议:
char x = 0;
volatile unsigned char *video = (volatile unsigned char *)(0xB8000 + x);
*video = 'A';
Run Code Online (Sandbox Code Playgroud)
这样,它应该工作.编译器假定video指针指向的值可以更改,然后不进行优化.但是,如果以后我想改变它,比如:
video = (volatile unsigned char *)(video + 2);
Run Code Online (Sandbox Code Playgroud)
我不应该将指针定义为volatile,像unsigned char * volatile video?那么编译器知道地址可以改变吗?
许多加密库包含类似于以下代码段的代码:
/* Implementation that should never be optimized out by the compiler */
static void optimize_proof_zeroize( void *v, size_t n )
{
volatile unsigned char *p = v;
while( n-- ) *p++ = 0;
}
Run Code Online (Sandbox Code Playgroud)
但是我的天真实现无法在优化编译器中存活:
/* Naive zeroization implementation */
static void naive_zeroize( unsigned char *c, size_t n)
{
int i;
for( i = 0; i < n; i++ )
c[i] = 0;
}
Run Code Online (Sandbox Code Playgroud)
该代码用于在释放内存之前将敏感数据归零.由于缓冲区不再使用,优化编译器假设它们可以安全地从编译的代码中删除zeriozation.
是什么阻止了第一个实施的优化?
我正在Linux环境下为ARM编写程序。它\xe2\x80\x99s不是一个低级程序,比如说在应用程序级别。
\n以下有什么区别?
\nint iData;
与
\nvolatile int iData;
它有特定于硬件的影响吗?
\n以下链接说"始终未访问设备寄存器的访问权限"
我的问题是,当访问存储器映射的设备寄存器时,我们是否需要易失性?
我正在使用nrf52微控制器(CORTEX 34F)处理器.我对主循环进行了变量检查,在主循环和定时器中断程序中都进行了修改.
主循环检查变量是否为真:
执行条件代码
将变量设置为false
没有volatile关键字,代码似乎不起作用,但当我将变量设置为volatile它似乎工作,但我不相信,因为:
任何答案,请;
if true执行正文代码2.列出项目
我们需要在关闭所有类型的编译器优化时使用volatile限定符,假设在启用编译器优化时需要它.
我阅读了有关SO Volatile和编译器优化的帖子,该文章说是,但没有给出任何需要它的特定用例.
有人可以指出仍然需要使用它们的情况,无论启用或禁用任何类型的优化.
static volatile组合使用变量说明符有什么区别?或者单独使用一个;喜欢static或volatile在微控制器编程?
我试图了解volatile关键字在C ++中的工作方式。
我看了一下“易失性”在C ++中可以防止哪些优化?。查看可接受的答案,看起来像volatile禁用了两种优化
我在https://en.cppreference.com/w/cpp/language/as_if找到了类似的信息。
对易失性对象的访问(读取和写入)严格按照发生它们的表达式的语义来发生。特别是,它们不会相对于同一线程上的其他易失性访问而重新排序。
我编写了一个简单的C ++程序,该程序对数组中的所有值求和,以比较Plain ints和volatile int的行为。请注意,部分和不会不稳定。
数组由不合格的ints 组成。
int foo(const std::array<int, 4>& input)
{
auto sum = 0xD;
for (auto element : input)
{
sum += element;
}
return sum;
}
Run Code Online (Sandbox Code Playgroud)
阵列由挥发性的int小号
int bar(const std::array<volatile int, 4>& input)
{
auto sum = 0xD;
for (auto element : input)
{
sum += element;
}
return sum;
}
Run Code Online (Sandbox Code Playgroud)
当我查看生成的汇编代码时,仅在纯ints的情况下使用SSE寄存器。据我所知,使用SSE寄存器的代码既没有优化读取,也没有对读取进行重新排序。循环已展开,因此也没有分支。我能解释代码源为何不同的唯一原因是:在发生累积之前,可以对易失性读进行重新排序吗?显然,sum它不是挥发性的。如果这种重新排序不好,是否存在可以说明问题的情况/示例?
使用clang9生成的代码
foo(std::array<int, 4ul> …Run Code Online (Sandbox Code Playgroud)