volatile关键字

嵌入式系统/ARM技术中的volatile在多线程中的应用 作者:曹忠明,华清远见嵌入式学院讲师。   volatile在词典中的意思是易变的,反复无常的。它在我们的程序设计中常常用到的。volatile是一个关键字,用来修饰一个变量,告诉编译器在编译的时候不要对其进行优化,在操作寄存器和多线程中这种用法是最常见的。   有这样一个例子:   #include   #include   void my_func();   int? i;   int main()   {   pthread_t my_thread;   int err,k;   if ((err = pthread_cr 立即下载

      在arm嵌入式做实验时碰到问题,下面对volatile关键字资料做个整理,记录下...

       volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改。用volatile关键字声明的变量i每一次被访问时,执行部件都会从i相应的内存单元中取出i的值。没有用volatile关键字声明的变量i在被访问的时候可能直接从cpu的寄存器中取值(因为之前i被访问过,也就是说之前就从内存中取出i的值保存到某个寄存器中),之所以直接从寄存器中取值,而不去内存中取值,是因为编译器优化代码的结果(访问cpu寄存器比访问ram快的多)。

 以上两种情况的区别在于被编译成汇编代码之后,两者是不一样的。之所以这样做是因为变量i可能会经常变化,保证对特殊地址的稳定访问。volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。

  volatile变量可能用于如下几种情况:

 (1) 并行设备的硬件寄存器(如:状态寄存器,例中的代码属于此类);

(2) 一个中断服务子程序中会访问到的非自动变量(也就是全局变量);

例如:

static int i=0;

int main(void)

{

     ...

     while (1){

if (i) dosomething();

}

}

/* Interrupt service routine. */

void ISR_2(void)

{

      i=1;

}

程序的本意是希望ISR_2中断产生时,在main函数中调用dosomething函数,但是,由于编译器判断在main函数里面没有修改过i,因此可能

只执行一次对从i到某寄存器的读操作,然后每次if判断都只使用这个寄存器里面的“i副本”,导致dosomething永远也不会被调用。如果

将变量加上volatile修饰,则编译器保证对此变量的读写操作都不会被优化(肯定执行)。此例中i也应该如此说明。

  (3) 多线程应用中被几个任务共享的变量。

   当要求使用volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而

且读取的数据立刻被保存。

  例如:

  volatile int i=10;

  int a = i;

  ……

  //其他代码,并未明确告诉编译器,对i进行过操作

  int b = i;

  volatile 指出 i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的汇编代码会重新从i的地址读取数据放在b中。而优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在b中。而不是重新从i里面读。这样以来,如果i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的稳定访问。

  注意,在vc6中,一般调试模式没有进行代码优化,所以这个关键字的作用看不出来。下面通过插入汇编代码,测试有无volatile关键字,对程序最终代码的影响:

#include <iostream>

using namespace std;

void main(){

      int i=5;

  int a=i;

   cout<<a<<endl;

  //下面汇编语句的作用就是改变内存中i的值,但是又不让编译器知道

  _asm{

        mov dword ptr[ebp-4],10H  //局部变量 1 <-[ebp-4]  局部变量 2 <- [ebp-8]

  }

  int b=i;

     cout<<b<<endl;

}

  然后,在调试版本模式运行程序,输出结果如下:

  a = 5b = 16

  然后,在release版本模式运行程序,输出结果如下:

  a = 5b = 5

  输出的结果明显表明,release模式下,编译器对代码进行了优化,第二次没有输出正确的i值。但我们把 i的声明加上volatile关键字,则输出均为a=5;b=16这说明这个关键字发挥了它的作用!

DrissionPage实战:5分钟搞定京东滑块验证码自动登录(附完整轨迹生成代码) 本文详细介绍了如何使用DrissionPage工具实现京东滑块验证码的自动化登录,包括环境配置、滑块缺口识别、拟人化轨迹生成算法及完整登录流程。通过物理运动学模型和智能识别技术,有效提升验证码破解成功率,适用于电商自动化场景。 阅读详情

相关推荐

逆向分析TikTok的Cronet网络库:定位libsscronet.so并Hook关键SSL函数

本文深入探讨了逆向分析TikTok的Cronet网络库的技术细节,重点介绍了如何定位libsscronet.so并Hook关键SSL函数。通过Java到Native的调用链路追踪、So库定位策略和SSL验证函数的动态Hook技巧,帮助开发者突破定制化网络库的协议加密防护,实现流量解密和协议分析。

weixin_27875131的博客 970

ARM嵌入式编译器-volatile关键字对编译器优化的影响

智能的(进行优化的)编译器可能会把变量的值临时储存在寄存器上,便于下次读取,以节约时间,这个过程被称为高速缓存。但是有一些agent在内存上改变了变量的值,寄存器上的还是旧数据,这样就出错了。如果被volatile 关键字修饰,编译器不会进行高速缓存,直接去内存中读取该变量的数据。编译器会优化什么将内存变量缓存到寄存器中。调整指令顺序,充分利用CPU指令流水线,进行指令重新排序读写指令。

DayDayUp 4712

从零开始用飞牛fnas搭建集成DeepSeek-R1的远程AI工作台

从零开始用飞牛fnas搭建集成DeepSeek-R1的远程AI工作台

AI+全栈,AI+应用,实操落地,前沿技术 3807

arm裸机点亮led volatile的理解

况下会使得这些副本中的值不同,这是不允许的,所以干脆用volatile,让它只。volatile,很可能由于编译器的优化,会先把值先写到一个缓冲区,到一定时候。当中断来的时候,相对应的位置1,而清0又不能向这位写0,向这位写1才是1才。(3)当地址是io端口的时候,读写这个地址是不能对它进行缓存的,这是相对。,因为同一个东西可能在不同的存储介质中有多个副本,有些情。有一个,没有其他的副本,这样就不会发生不同步的问题。再写到io端口,这样就不能使数据及时的写到io端口,1.编写启动文件start.s。

m0_51404095的博客 189

ml307 二次开发

中移物联网旗下4g模组官方网站官方教程id=514官方客户不知道啥时候上班 早上10点也说不在服务时间内 找不到官方的sdk下载路径。

myWorld001的博客 2882

Yolov5 多边形标签转换,所有json文件自动转成txt格式[详细过程]

注:labelme是麻省理工(MIT)的计算机科学和人工智能实验室(CSAIL)研发的图像标注工具,人们可以使用该工具创建定制化标注任务或执行图像标注,项目源代码已经开源。通过labelme对图进行标注后,得到的是json文件,而Yolov5对数据进行模型构建的时候,读取需要的是txt格式的文件。txt_outer_path——保存txt文本的文件夹的绝对路径。json_name——json_name是json文本的名字。json_floder——读取json的文件夹的绝对路径。

Pandas_007的博客 1万+

ARM启动代码栈和调用C语言以及volatile简单使用

上一篇写了要关闭看门狗,后面需要用到的时候再开 下面的启动代码依然要用汇编写 为什么用汇编不用C语言 因为这时候不具备C语言的运行环境,所以需要创造一个环境给C语言。 为什么要设置栈 因为C语言的局部变量都是用栈来实现的。只有设置了合法的栈地址,局部变量才可以定义。 为什么平时的不用设置 单片机程序(譬如51单片机)或者编写应用程序时并没有去设置栈,但是C程序还是可以运行的。原因是:在单片机中由...

fsczp的博客 455

ArcGIS中如何计算多个点到特定线的最短距离

现有一个点图层和一个面图层,怎么来计算这些点到这个面图层,两个面的公共边的最短直线距离呢? 1.首先得将两个图层都转为 投影坐标系 打开工具箱-数据管理工具-要素-面转线 ​ ​ 2.将面图层设为输入要素 注意要将“识别和存储面邻域信息”勾选 ​ 3.面转线成功后 打开线属性表,线图层拥有了 LEFT_FID和RIGHT_FID两个字段 ​ 4.按属性选择,表达式中输入 “LEFT_FID”<>-1 即可选出两个面的公共边 ​再将选...

GIS蒲公英的博客 6715

arm中宏定义地址关键字volatile解析

在arm程序代码中我们经常看到开头会出现下面的代码: 例子:  #define IOPIN (*((volatile unsignedlong *)0xE0028000)) 这个语句对于不同的计算机体系结构,设备可能是端口映射,也可能是内存映射的,有点类似大小端的转换。如果系统结构支持独立的IO地址空间,并且是端口映射,就必须使用汇编语言完成实际对设备的控制,因为C语言兵没有提供真正的“端口

lieyanhaipo的专栏 2680

【数字图像处理第四版课后习题答案】第2章 数字图像基础(含英文原版)

如图 P2.3 所示,视网膜图像中与点相对应的直径 x 是由类似的三角形得到的。即得出 x = 0.085d。根据第 2.1 节中的讨论,并结合一些自由解释,我们可以将眼窝视为一个方形传感器阵列,拥有大约 337,000 个元素,这相当于一个大约 580×580 个元素的阵列。假设元素间距相等,则在 1.5 毫米长的直线上有 580 个元素和 579 个空间,共计 1,159 个。换句话说,如果一个点的直径 d<1.3×10-6 m,或者 d<15.3×10 m,眼睛就无法检测到这个点。

weixin_56463218的博客 1万+

【赛题解析&命令脚本配置】2024年第十七届山东省技能大赛 | 网络系统管理”赛项-模块B:Linux服务部署 & ⑤客户端OutsideCli和InsideCli工作任务

【赛题解析&命令脚本配置】2024年第十七届山东省技能大赛 | 网络系统管理”赛项-模块B:Linux服务部署 & ⑤客户端OutsideCli和InsideCli工作任务 | 【赛题解析&命令脚本配置】2024年第十七届山东省技能大赛 | 网络系统管理”赛项-模块B:Linux服务部署 & ⑤客户端OutsideCli和InsideCli工作任务

君逍遥o 319

寄存器操作*(volatile uint32 *)含义详解

#define PINMUX3             *( volatile Uint32* )( 0x01C40000+ 0x0C )  PINMUX3 &= ~0x00600000;   分析: 将以上两句合成一条语句相当于 *( volatile Uint32* )( 0x01C40000+ 0x0C )  &= ~0x00600000; 意思是将0x01C40000+ 0x0

持之以恒-先苦后甜 1万+

微信小程序 - 下单账号和支付账号不一致,请核实后再支付(微信小程序或微信H5页面/微信公众号网页支付时报错:“下单账号和支付账号不一致,请核实后再支付”,买家微信支付时提示错误)详细排查和解决方案!

微信支付出现 “下单账号与支付账号不一致,请核实后再支付”微信小程序下单账号与支付账号不一致不让支付,微信公众号网页 微信H5页面JS-SDK支付时出现错误:下单账号和支付账号不一致,请核实后再支付,openId导致的微信中“下单账号和支付账号不一致”原因及解决办法,调用统一下单所传openId与实际支付用户的openId不一致,微信支付jssdk报错,检查了没有不一致依然报错怎么办,微信支付下单账号和支付账号不一致,请核实后再支付,微信支付功能用JSAPI支付,H5页面负责下单并支付jsapi,微信调起支

🏆 前端领域优质创作者 5330

C#关键字volatile

在这个例子中,count字段被声明为volatile。在这里,hasData变量被声明为volatile,确保了生产者线程对hasData的修改能够被消费者线程及时看到,并且消费者线程对hasData的修改也能被生产者线程及时看到,从而保证了生产者 - 消费者模式的正确运行。例如,有两个线程,一个线程(线程 A)在不断地更新一个共享变量的值,另一个线程(线程 B)在读取这个共享变量的值。因为它要求对变量的每次访问都直接从主内存中进行,而不是从线程的工作内存(缓存)中进行,这会增加内存访问的开销。

2401_83367969的博客 2148

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

volatile关键字详解

缓存一致性协议: 每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当处理器要对这个数据进行修改操作的时候,会强制重新从系统内存里把数据读到处理器缓存里。在多线程环境下,CPU轮流切换线程执行,有可能某个线程修改了数据,准备回主内存,此时CPU切换到另一个线程修改了数据,并且写回到了主内存,此时就导致数据的不准确。的作用就是,当某个线程工作内存中的值与主内存中的值,如果不相同就会一直。

努力分享一些干货 1837

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

什么时候使用volatile关键字?

想必大家平时都见过volatile关键字,可是你知道什么时候需要使用volatile关键字吗? 直接看下面代码: int a = 100; while (a == 100) { // code } 这段程序编译时,如果编译器发现程序始终没有企图改变a的值,那它可能就会优化这段代码,变成while(true)的死循环使得程序执行的更快,然而编译器有时候也会做过度优化,它有时候可能没有意识到程序会改变a的值,却做了这种优化导致程序没有产生预期的行为。 这里为了产生预期的行为,需要阻止编译器做这种优化

qq_29426201的博客 2406

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

volatile关键字的作用

在我们了解volatile关键字之前,首先看一下代码; public class Mythread implements Runnable{ private boolean flag = false; @Override public void run() { try { //当前线程让出资源 sleep(20...

qq_37031675的博客 5060

14. Java中 volatile 关键字

volatile 关键字概念介绍,从整体层面了解 volatile 关键字;volatile 关键字与 synchronized 关键字的区别,这是本节的重点内容之一,了解 volatile 关键字与 synchronized 关键字的区别,才能更好地区分并掌握两钟关键字的使用;volatile 关键字原理介绍,也是本节课程的重点之一;volatile 关键字的使用,是本节课程的核心内容,所有的知识点都是围绕这一目的进行讲解的。概念。

这是一个web全栈开发的博客,取其精华去其糟粕,争取让大家一看就懂,一学就会,一用就成~ 1279

浅析volatile关键字

volatile 关键字声明的类型变量表示可以被某些编译器未知的因素(操作系统、硬件、其它线程等)更改,每次访问时都必须从内存中取出值(没有被 volatile 修饰的变量,可能由于编译器的优化,从 CPU 寄存器中取值)const 可以是 volatile(如只读的状态寄存器)指针可以是 volatile。

螺蛳粉只吃炸蛋的走风的博客 1052

C++中volatile关键字的作用

对于较官方的解释是:volatile作为指令关键字,确保本条指令不会因编译器的优化而被省略,即系统每次从变量所在内存读取数据而不是从寄存器读取备份。 下面将进行详细说明: 易变性 编译器对volatile修饰的变量,当要读取这个变量时,任何情况下都会从内存中读取,而不会从寄存器缓存中读取(因为每次都从内存中读取体现出变量的“易变”) 对于非volatile变量 对 b = a + 1;这条语句,...

liufangping的博客 4973

volatile关键字总结

c++的volatile关键字

papaya的博客 3216

对 volatile 关键字的理解

对 volatile 关键字的理解

技术回忆录 1757

volatile关键字的作用、原理

综上,其实volatile保持内存可见性和防止指令重排序的原理,本质上是同一个问题,也都依靠内存屏障得到解决。更多内容请参见JVM相关书籍。volatile关键字的作用、原理。

攻城狮不是猫 1084
上一篇: 操作系统实验-内存管理
下一篇: 操作系统练习题(2)
macandroid
博客等级 码龄14年 35粉丝 28原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值