发表于: 2007年 05月11日 11:13 发表主题: 关于volatile关键字的疑惑? 引用并回复 编辑/删除帖子 删除这个主题
struct {
int i,
int j,
......
}A;
volatile A *ptr;
ptr = (A *) kmalloc(sizeof(A), GFP_KERNEL);
编译器不会对ptr指针进行任何优化,它会不会对结构体成员进行优化,即ptr->i和
ptr->j;
这时执行
kfree(ptr);
提示警告:
“passing argument 1 of 'kfree' discards qualifiers from pointer target type”
什么意思?
如果定义
struct {
volatile int i,
volatile int j,
......
}A;
A *ptr;
ptr = (A *) kmalloc(sizeof(A), GFP_KERNEL);
它不会对结构体成员进行优化,即ptr->i和ptr->j
这时执行
kfree(ptr);
不会出现警告。
这两种方式是否有区别。
关于volatile关键字的疑惑?
-
- 帖子: 6
- 注册时间: 2007-04-18 14:53
-
- 帖子: 1
- 注册时间: 2007-06-01 10:58
-
- 帖子: 16
- 注册时间: 2008-01-19 19:33
个人理解:
volatile是“易变的”,是针对编译器优化的关键词,因为编译一个子程序(它接收一个参数a),为了提高访问速度,通常会访问a的一个拷贝,也叫值传递;而使用volatile后理论上会强制从原来变量处(子程序外)读取,这对于一些应用是必须的,比如定时器的定时值寄存器,它除了会被程序改变,还会被外部硬件改写。
你这里的是释放一个指针,应该来讲它是不会被外部硬件改变,因为一旦改变,你就无法了释放这个指针所指的struct结构体,这实际上也是一种内存泄露;
所以编译器的意思应该是“既然它是不会被随便改变的,因此对于Kfree函数来说volatile这个关键字可以不要”,这个警告可以忽略。
以上是个人看法,有错的希望大家指正
volatile是“易变的”,是针对编译器优化的关键词,因为编译一个子程序(它接收一个参数a),为了提高访问速度,通常会访问a的一个拷贝,也叫值传递;而使用volatile后理论上会强制从原来变量处(子程序外)读取,这对于一些应用是必须的,比如定时器的定时值寄存器,它除了会被程序改变,还会被外部硬件改写。
你这里的是释放一个指针,应该来讲它是不会被外部硬件改变,因为一旦改变,你就无法了释放这个指针所指的struct结构体,这实际上也是一种内存泄露;
所以编译器的意思应该是“既然它是不会被随便改变的,因此对于Kfree函数来说volatile这个关键字可以不要”,这个警告可以忽略。
以上是个人看法,有错的希望大家指正
-
- 帖子: 33
- 注册时间: 2008-02-04 8:35
volatile
volatile的本意是“易变的”
由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化。比如:
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也应该如此说明。
一般说来,volatile用在如下的几个地方:
1、中断服务程序中修改的供其它程序检测的变量需要加volatile;
2、多任务环境下各任务间共享的标志应该加volatile;
3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;
另外,以上这几种情况经常还要同时考虑数据的完整性(相互关联的几个标志读了一半被打断了重写),在1中可以通过关中断来实现,2中可以禁止任务调度,3中则只能依靠硬件的良好设计了。
volatile的本意是“易变的”
由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化。比如:
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也应该如此说明。
一般说来,volatile用在如下的几个地方:
1、中断服务程序中修改的供其它程序检测的变量需要加volatile;
2、多任务环境下各任务间共享的标志应该加volatile;
3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;
另外,以上这几种情况经常还要同时考虑数据的完整性(相互关联的几个标志读了一半被打断了重写),在1中可以通过关中断来实现,2中可以禁止任务调度,3中则只能依靠硬件的良好设计了。
- eexpress
- 帖子: 58428
- 注册时间: 2005-08-14 21:55
- 来自: 长沙