对变量声明为volatile const的浅析

关于Linux操作系统,发行版、内核的问题

版主: timeboy, absfreedom

对变量声明为volatile const的浅析

帖子lillian4891 于 2010-03-04 1:07

volatile 相当于告诉编译器, 由它声明的变量是易变的, 不确定的, 可能由外部程序 (如中断程序) 改变的, 禁止编译器对其读写操作进行优化。
const修饰的变量则表示该变量在程序中只能读不能写,因此,也称其为常量。

当对变量定义成volatile const时,“变”与“不变”之间是不是常常让我们困惑呢?既是常量,但又是可能被修改的……,怎么可以这么定义呢?

我们先好好理解变与不变的意思。 程序运行要先编译再真正被CPU执行,即包含了把源代码转化为机器代码的过程的编译期 和 实际代码在CPU执行的运行期。const ,只是编译器保证在“源代码”里面,没有对该变量进行修改的地方,而实际运行的时候则不是编译器所能管的了。
volatile的所谓“可能被修改”,是指“在运行期间”可能被修改。也就是告诉编译器,这个变量不是“只”会被这些“源代码”所操纵,其它地方也有操纵它们的地方。

volatile会禁止编译器优化。
什么是编译器优化呢?它指的是当一个变量被声明为const时,编译器认为该变量在某一段代码(如一个函数)中不会发生改变,就会将该变量存储到CPU的寄存器,从CPU寄存器读写数据的速度要远远快于从内存读取数据。
当加上volatile时禁止编译器优化,也就是说,不允许将该数据保存到CPU寄存器,因为保存到CPU寄存器的变量可能在某些情况下被改变,例如,另一个线程可能会改变该寄存器的值,这样就会导致你原本以为是const的变量发生了改变,导致了问题。
而使用volatile const声明就避免了这种情况。

不矛盾了吧^^
lillian4891
 
帖子: 3
注册: 2010-02-04 13:35

Re: 对变量声明为volatile const的浅析

帖子welfear 于 2010-03-04 3:06

“volatile 相当于告诉编译器, 由它声明的变量是易变的, 不确定的, 可能由外部程序 (如中断程序) 改变的, 禁止编译器对其读写操作进行优化。
const修饰的变量则表示该变量在程序中只能读不能写,因此,也称其为常量。

当对变量定义成volatile const时,“变”与“不变”之间是不是常常让我们困惑呢?既是常量,但又是可能被修改的……,怎么可以这么定义呢?

我们先好好理解变与不变的意思。 程序运行要先编译再真正被CPU执行,即包含了把源代码转化为机器代码的过程的编译期 和 实际代码在CPU执行的运行期。const ,只是编译器保证在“源代码”里面,没有对该变量进行修改的地方,而实际运行的时候则不是编译器所能管的了。
volatile的所谓“可能被修改”,是指“在运行期间”可能被修改。也就是告诉编译器,这个变量不是“只”会被这些“源代码”所操纵,其它地方也有操纵它们的地方。”

大致可以这么理解。

“volatile会禁止编译器优化。
什么是编译器优化呢?它指的是当一个变量被声明为const时,编译器认为该变量在某一段代码(如一个函数)中不会发生改变,就会将该变量存储到CPU的寄存器,从CPU寄存器读写数据的速度要远远快于从内存读取数据。”

对于const变量和CPU寄存器之间的关系,需要证据。

“当加上volatile时禁止编译器优化,也就是说,不允许将该数据保存到CPU寄存器,因为保存到CPU寄存器的变量可能在某些情况下被改变,例如,另一个线程可能会改变该寄存器的值,这样就会导致你原本以为是const的变量发生了改变,导致了问题。
而使用volatile const声明就避免了这种情况。 ”

另一线程有可能修改此变量也就是内存值,但肯定不会修改CPU寄存器。
最后由 welfear 编辑于 2010-03-04 6:20,总共编辑了 1 次
技法无高下 功力有深浅
welfear
 
帖子: 534
注册: 2008-12-20 12:19

Re: 对变量声明为volatile const的浅析

帖子true 于 2010-03-04 4:43

楼上回复需要高亮
I disapprove of what you say, but I will defend to the death your right to say it. -- Voltaire
头像
true
 
帖子: 625
注册: 2008-10-21 22:17

Re: 对变量声明为volatile const的浅析

帖子welfear 于 2010-03-04 6:22

true 写道:楼上回复需要高亮

不会玩这玩意。
技法无高下 功力有深浅
welfear
 
帖子: 534
注册: 2008-12-20 12:19

Re: 对变量声明为volatile const的浅析

帖子lillian4891 于 2010-03-04 17:58

我也是常常看看这种定义方式 最近总算明白了些
也许你哪天也就遇见它了 呵呵~~
lillian4891
 
帖子: 3
注册: 2010-02-04 13:35

Re: 对变量声明为volatile const的浅析

帖子welfear 于 2010-03-04 18:51

lillian4891 写道:我也是常常看看这种定义方式 最近总算明白了些
也许你哪天也就遇见它了 呵呵~~

Kernel里不会出现所谓的volatile const。
这种论述在Linux/Documentation/volatile-considered-harmful.txt中已经说明了。
即使在用户空间也不应该依赖volatile关键字实现多线程同步,volatile仅仅是建议。
你的第二段论述好像是猜测的,缺少证据。
你的第三段论述我认为有问题,被你的第二段误导了。
技法无高下 功力有深浅
welfear
 
帖子: 534
注册: 2008-12-20 12:19

Re: 对变量声明为volatile const的浅析

帖子lillian4891 于 2010-03-05 9:51

welfear写道:
“Kernel里不会出现所谓的volatile const。
这种论述在Linux/Documentation/volatile-considered-harmful.txt中已经说明了。
即使在用户空间也不应该依赖volatile关键字实现多线程同步,volatile仅仅是建议。
你的第二段论述好像是猜测的,缺少证据。
你的第三段论述我认为有问题,被你的第二段误导了。”

我还没读过Linux/Documentation/volatile-considered-harmful.txt,也许Kernel中很少出现volatile const,但内核开发者接触的我想不会仅限于内核的吧。
我可没说volatile用来保证多线程同步啊,但在我们希望某个变量不要被一些中断或其他进程所改变而引起一些数据不一致的错误时,使用volatile就是一个提醒,这个变量是“易变的”,禁止编译器优化,我们想读取这个变量的值时就从内存里读取,而不会从寄存器中读取了。多线程同步我想应该是通过锁,信号量,完成量等一些方式来控制的吧。
第二段论述的关于编译过程和运行过程,我想可以这样来理解。如在代码中定义const int a,它会告诉我们a是只读的,当后面代码出现对a的重新赋值的语句时,编译时肯定会报错,const是对编译期间而言;而某些所谓“易变的”变量,它的易变性也是因为这个变量可能会被某些运行的进程所修改,所以理解volatile的易变是因为运行期间的一些进程才赋予了这个变量这种特性。
第三段论述挺好的啊,有问题?
lillian4891
 
帖子: 3
注册: 2010-02-04 13:35

Re: 对变量声明为volatile const的浅析

帖子hippo 于 2010-03-12 9:05

在ARM上要去写某个内存地址上的内容时候经常会用到volatile ,就是为了不优化吧
hippo
 
帖子: 96
注册: 2009-10-19 16:58


回到 Linux操作系统

在线用户

正在浏览此版面的用户:没有注册用户 和 2 位游客