免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: 南海一钓叟

那为大侠给俺讲讲cache和volatie变量的关系 [复制链接]

论坛徽章:
0
发表于 2008-02-29 19:35 |显示全部楼层
原来我也不懂,不过现在懂了

论坛徽章:
0
发表于 2008-02-29 20:04 |显示全部楼层
没想到成都还有这么厉害的高手哈,佩服!

论坛徽章:
0
发表于 2008-02-29 20:12 |显示全部楼层
发现一个小问题,和主题无关,曾经讨论过
3楼 do_someting(如果是函数)可能会修改全局的i,而编译器不可能去检查这个事实,所以
while(i)
do_something();
不是例子

while(i) {
  /**/
}

论坛徽章:
0
发表于 2008-02-29 20:14 |显示全部楼层
终于明白snoop的意义...

论坛徽章:
0
发表于 2008-03-01 23:07 |显示全部楼层
关于 volatile 我觉得这样的解析最容易理解:
如果编译器在代码中发现对同一地址的两次访问之间,没有对该地址进行写操作,那么编译器将优化为第一次寻址读该地址时取得的值作为第二次寻址的值,而并不是再做第二次物理上的 I/O 寻址操作。volatile 关键字指示编译器进行强制 I/O 寻址,因为编译器那样的优化,可能并不是我们真正期望的,譬如那个地址上连接着一个传感器上的寄存器,那么实际上,可能该寄存器的值是被传感器自身不断刷新的。因此,我们必要要求CPU每次都进行 I/O 操作。

论坛徽章:
0
发表于 2008-03-02 12:31 |显示全部楼层
楼主应聘的是嵌入式的嘛

论坛徽章:
0
发表于 2008-03-02 18:29 |显示全部楼层
Do you volatile? should you?

by Dr. Kevin P. Dankwardt

Volatile is an ANSI C type modifier that is frequently needed in C code that is part of signal/interrupt handlers, threaded code, and other kernel code, including device drivers. In general, any data that may be undated asynchronously should be declared to be volatile. Incidentally, this issue is not related to CPU caches, except that re-loading of variables into registers may involve cache hits or misses.

Why Use Volatile?

The reason to use volatile is to ensure that the compiler generates code to re-load a data item each time it is referenced in your program. Without volatile, the compiler may generate code that merely re-uses the value it already loaded into a register.

Volatile advises the compiler that the data may be modified in a manner that may not be determinable by the compiler. This could be, for example, when a pointer is mapped to a device's hardware registers. The device may independently change the values unbeknownst to the compiler.

With gcc the -O2 option is normally required to see the effect of not using volatile. Without -O2 or greater optimization, the compiler is likely to re-load registers each time a variable is referenced, anyway. Don't blame the optimizer if a program gets incorrect results because the program does not use volatile where required.

For example, if two threads share a variable, sum, and one or both threads modify it, then the other thread may use a stale value in a register instead of going back to memory to get the new value. Instead, each time the thread references sum, it must be re-loaded. The way to insure this occurs in ANSI C is to declare sum to be volatile.

Example 1.
// Program to measure the difference between volatile and not

// written by Kevin P. Dankwardt k@kcomputing.com

// 3 March 2005


#include <stdio.h>
#include <signal.h>
#include <sched.h>
#include <sys/time.h>

#ifndef VOLATILE
#define VOLATILE
#endif

VOLATILE int total=0;
void handle(int signo)
{
    if (signo == SIGALRM)
         {
          printf("Total = %d\n",total);
          exit(0);
         }
    total++;
}
int main ()
{
   VOLATILE unsigned x=0;
   VOLATILE int i,j;
   struct sched_param param;
   struct itimerval val;
   
   val.it_interval.tv_sec = 0;
   val.it_interval.tv_usec = 10000; // 10 ms

   val.it_value.tv_sec = 0;
   val.it_value.tv_usec = 10000; // 10 ms

   setitimer(ITIMER_VIRTUAL, &val, NULL);
   param.sched_priority = 99;
   if (sched_setscheduler(0, SCHED_RR, &param) ==-1) {
       perror("setting priority");
       exit(1);
   }
   #define BIGNUM (1000)
   
   alarm(10);
   signal(SIGALRM,handle);
   signal(SIGVTALRM,handle);
   while (total < 100 )
   {
        for (i=0; i<BIGNUM; i++)
            {
            for (j=0; j<BIGNUM; j++)
                   x =  x+j ;
            }
   }
   printf("x = %u\n",x); // so optimizers doesn't throw away the loop

   printf("total = %d\n",total);
}


The use of volatile can be required to get correct answers. For example the program wrong will give incorrect results when it is compiled -O2 and without volatile. This slightly obtuse program is designed to stop after 100 ticks of an interval timer that ticks at 100Hz and print the value of the variable total. The tick count is incremented in the signal handler. When the count gets to 100, the program should terminate. If the tick count does not get to 100 within 10 seconds then an alarm goes off and the program terminates.

By compiling the program as:

gcc -O2 -DVOLATILE=volatile wrong.c -o wrong_v

you will see, (unless your program is preempted for quite a while), that the count gets to 100 and the program terminates as designed. With the program compiled as

gcc -O2 wrong.c -o wrong_nv

you will see, that the count becomes greater than 100 as shown when the handler prints it, but, the while loop does not terminate.

Incidentally, attempts to determine what is happening may thwart your efforts. For example, a function call, such as to printf(), or the use of a breakpoint, in the loop, will likely spill and re-load the registers.
Syntax

The keyword volatile is similar to the const keyword. Volatile is used to modify a type. Thus an int, const int, pointer, etc. may be declared to be volatile. In addition, a point may be declared to be a pointer to volatile. A pointer to volatile means that the data to which the pointer refers is volatile as opposed to the pointer itself. Of course, both the pointer and to which it refers, may be declared to be volatile.

To declare a volatile int do:

volatile int v;

and to declare vp to be a pointer to a volatile int do:

volatile int *vp;

Since deciphering C declarations can be difficult you may want to consult the C declaration chapter in the Sun manual. This manual references the Decoder Flowchart that can be used to help decipher declarations.

In addition, Linux may have the cdecl(1) program that can be used to translate C declarations to English, as for example, in

echo 'explain volatile int *v' | cdecl

which will answer with

declare v as a pointer to volatile int

Reading C declarations is made simpler when you realize that they are written boustrophedonically. Of course, even knowing the definition of boustrophedonically doesn't really help. The idea is that C declarations are interpreted based on the tricky precedence of operators such as "*", "[]", and "()".

Performance Issues
In some sense, volatile is the opposite of register. Thus, one can expect to lose performance. This means don't use volatile when it is not needed.
Example 2.
// Program to measure the difference between volatile and not

// written by Kevin P. Dankwardt k@kcomputing.com

// 3 March 2005

// compile with -O2 flag to see volatile make a difference

// compile with -DVOLATILE=volatile to use volatile.

// 3 March 2005


#include <stdio.h>
#include <signal.h>
#include <sched.h>

int total=0;
#ifndef VOLATILE
#define VOLATILE
#endif
void handle(int signo)
{
    int t=total;
    char type[100];
    printf("%d\n", t);
    exit(0);
}
int main ()
{
   VOLATILE int x=0;
   VOLATILE int i,j;
   struct sched_param param;

   param.sched_priority = 99;
   if (sched_setscheduler(0, SCHED_RR, &param) ==-1) {
       perror("setting priority");
       exit(1);
   }
   #define BIGNUM (1span>
   
   alarm(10);
   signal(SIGALRM,handle);
   for (i=0; i<BIGNUM; i++)
       {
       total++;
       for (j=0; j<BIGNUM; j++)
              x =  x+j ;
       }
   printf("x = %d\n",x); // so optimizers doesn't throw away the loop

}


In our performance example we can see the difference that volatile may make. If we compile this program with and without VOLATILE defined as volatile we see an average number of iterations of almost 5,000 for the volatile case and almost 20,000 for the non-volatile case. Yikes! Remember that we must compile both of them with the -O2 option. (These iteration counts were made on a 400Mhz AMD-K6.)

Linux Examples
The use of the volatile keyword is common in the Linux kernel source. For example, of the 10,607 .c and .h files in the Fedora Core 1, Linux kernel source directory, 1,694 have the string "volatile" in them somewhere. As an example, the file drivers/net/eepro.c uses volatile in three places.

385: volatile s32 cmd_status; /* All command and status fields. */
392: volatile s32 status;
764: volatile s32 *self_test_results;

Generated Code
By examining the code generated by the compiler one can see the difference volatile makes. In this simple example we can see the x86 assembly language when volatile is used and when volatile is not used.
Quiz Yourself
What is volatile in each of the following examples? Are they all legal declarations?

1) volatile int *s1;
2) int* volatile s2;
3) volatile int* volatile s3;
4) const volatile int * volatile s4;
5) volatile int * (*f)(volatile int *);

Check your answers.
Summary

The volatile keyword is relatively unknown. There are times when its use is required for correct operation of C/C++ programs. In general, whenever a variable may be altered asynchronously, such as by a signal handler or mapped hardware, the variable must be declared to be volatile.

Since volatile prevents re-using values in registers, volatile comes with a performance penalty that can be substantial.

Also, since declarations involving volatile can be difficult to decipher you may want to use cdecl(1).

原文链接 http://www.linuxdevices.com/articles/AT5980346182.html

[ 本帖最后由 sirouni 于 2008-3-2 18:45 编辑 ]

论坛徽章:
0
发表于 2008-03-03 10:43 |显示全部楼层
volatile 跟以前的 register 相反. register 告诉编译器尽量将变量放到寄存器中使用, 而volatile 强制将更改后的值写回内存(无论是cache还是内存). 如果不写回内存, 对于一些全局共享的变量, 可能导致不一致问题.

[ 本帖最后由 srdrm 于 2008-3-3 10:47 编辑 ]

论坛徽章:
0
发表于 2008-03-03 11:15 |显示全部楼层

回复 #1 南海一钓叟 的帖子

我的博客里面有几篇关于volatile变量的文章
可以去看看

http://blog.chinaunix.net/u1/52454/showart_487024.html

论坛徽章:
0
发表于 2008-03-03 11:19 |显示全部楼层

回复 #39 sohu2000000 的帖子

OK,谢谢咯
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP