跳到主要内容

17 volatile,让我保持原样

嵌入式开发中的常见情形

实例分析

  • 设备启动及初始化

    //device.c
    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.h>

    int g_ready = 0;

    void* init_device(void* args)
    {
    sleep(5);

    g_ready = 1;

    printf("init_device() - device status : g_ready = %d\n", g_ready);
    }

    void launch_device()
    {
    pthread_t tid = 0;

    pthread_create(&tid, NULL, init_device, NULL);
    }
    //main.c
    #include <stdio.h>
    #include <pthread.h>

    extern const int g_ready;

    int main()
    {
    launch_device();


    while( g_ready == 0 )
    {
    sleep(1);

    printf("main() - launching device : g_ready = %d\n", g_ready);
    }

    printf("main() - device status : g_ready = %d\n", g_ready);

    return 0;
    }
  • 问题分析

    • 编译优化时,编译器根据当前文件进行优化
    • 编译器能够发现变量“不可能”被改变(const 全局变量)
    • 为了效率上的提高,编译将变量值进行缓存
    • 缓存的方式为:把变量值从内存中读取进入寄存器
    • 每次访问变量时直接从寄存器读取对应值
  • 解决方案

    • 使用volatile修饰可能被“意外”修改的变量(内存)
      • volatile修饰的变量是一种“易变的”变量
      • volatile可理解为“编译器警告指示字”
      • volatile告诉编译器必须每次去内存中取变量值

编程实验

  • 使用volatile修饰变量

  • 问题

    如何理解const和volatile同时修饰变量?在语义上是否矛盾?

  • const和volatile

    • const表示被修饰的变量不能出现在赋值符号左边
    • volatile表示使用变量时直接从内存取值
    • const和volatile同时修饰变量时互不影响其含义

小结

  • 编译优化时,编译器只根据当前文件进行优化
  • 编译器的优化策略可能造成一些“意外”
  • volatile强制编译器必须每次从内存中取变量值
  • const和volatile同时修饰变量时互不影响其含义