在
此類型中,方式 Main 將啟動新的執行緒來履行方式 Thread2。此方式會將數值貯存到稱為 result 的非 Volatile 物件內,接著將 true 貯存於 finished 的 Volatile 物件內。主履行緒將守候物件 finished 設成
true後,再接著讀取物件 result。因為 finished 已宣告成 volatile,主履行緒必需從物件 result 中讀取數值
143翻譯若物件 finished 未宣佈成 volatile,主履行緒就可能在看到存至 finished 以後,才會看到貯存至
result,是以主履行緒會從物件 result 中讀到數值 0。將 finished 宣告成 volatile 物件可以避免這類紛歧致的狀態産生。
Volatile這玩意兒用在單晶片的C說話較多
例如:Volatile char wait;
void xxx(void)
{
wait=1;
while (wait!=0);
.....
.....
}
void timer0(void) interrupt 1
{
wait=0;
.......
}
xxx()中就是等一個timer中斷才執底下工作.
假如不寫Volatile會被編譯器省略掉.
因為wait=1;何來wait會等於0
"volatile"是一個樞紐字(keyword),用來潤飾詞資料型態,與const有對應的關係。
是說話關鍵字的話,就不會泛起在標頭檔內的界說。
"volatile sig_atomic_t read_flag = 1;"
read_flag是一個為sig_atomic_t的資料型態,透過volatile的潤色,申明sig_atomic_t在程式中,可以在任何的時候下被個別的 thread 所點竄
也就是說,
可能主程式main在利用的同時,I/O Device或另外一個thread也在哄騙或指定這個read_flag 來透過溝通的感化翻譯
【"關於volatile要害字的說明和測試"】
volatile環節字是一種類型潤色符,用它宣佈的類型變數示意可以被某些編譯器未知的身分更改,比如:功課系統、硬體或其他履行緒等。碰到這個要害字宣佈的變數,編譯器對存取該變數的程式碼就不再進行最佳化,從而可以供應對特殊位址的不亂存取。
利用該關頭字的例子如下:
【C說話內"volatile"的用法和功用】
int a = i;
printf("i= dn",a);
The compilation system tries to reduce code size and execution
time on all machines翻譯社 by optimizing code. It is programmer
responsibility to inform compilation system that certain code (or
variable) should not be optimized. Many programmers do not understand
when to use volatile to inform compilation system that certain code
should not be optimized or what it does. Although (no doubt) their
program work, they do not exploit the full power of the language.
A variable should be declared volatile whenever its
value can be changed by something beyond the control of the program in
which it appears, such as a concurrently executing thread. Volatile,
can appear only once in a declaration with any type specifier; however,
they cannot appear after the first comma in a multiple item
declaration. For example, the following declarations are legal
More ways to map memory
volatile int p = 3;
declares and initializes an object with type volatile int whose value will be always read from memory.
Volatile T a =3;
T volatile a=3;
The declaration declares and initializes an objet with type volatile T whose value will be always read from memory
T* volatile ptrv;
Use of volatile
- An object that is a memory-mapped I/O port
- An object variable that is shared between multiple concurrent processes
- An object that is modified by an interrupt service routine
- An automatic object declared in a function that calls setjmp and
whose value is-changed between the call to setjmp and a corresponding
call to longjmp
Conclusion
*ptr = 0;
while(*ptr){
*ptr = 4 ;
*ptr = 0 ;
}
*ptr = 0
while(0) {
}
*ptr is assigned 0 before value 4 is used ( and value of *ptr never changes ( same constant is always assigned to it)
volatile keyword is used to suppress these optimization the compiler
assumes that the value can change any time 翻譯社 even if no explicit code
modify it
to suppress all optimization declare ptr as
volatile char * const ptr = (volatile char*)0x16
this declaration say the object at which ptr points can change without notice , but that ptr itself is a constant whose value never change
/listing 3: difference between listing 1 and listing 3 ***/
< .file"vol.c"
---
> .file"wvol.c"
< movl$3翻譯社 -4(%ebp)
< movl-4(%ebp)翻譯社 %eax
< pushl%eax
> pushl$3
< movl$5翻譯社 -4(%ebp) / * store in stack */
From above listing 3 it is clear that when you use setjmp and
longjmp, the only automatic variables guaranteed to remain valid are
those declared volatile.
/*Listing1: Assembly code fragment of above program
Produced by cc compiler when volatile is used*/
.file"vol.c"
main:
pushl%ebp
movl%esp, %ebp
subl$20翻譯社 %esp
movl$3, -4(%ebp)
pushl$buf
call_setjmp
addl$16, %esp
testl%eax, %eax
je.L18
subl$8, %esp
movl-4(%ebp), %eax
pushl%eax
pushl$.LC0
callprintf
movl$0, (%esp)
callexit
.p2align 2
.L18:
movl$5, -4(%ebp)
subl$8, %esp
pushl$1
pushl$buf
calllongjmp
#include <thread.h>
#include <stdio.h>
volatile int num ;
void* foo()
{
while(1) {
++num ;
sleep(1000);
}
}
main()
{
int p ;
void *targ =NULL ;
thread_t id ;
num = 0;
p = thr_create((void*)NULL 翻譯社 0,foo,targ,0,&id);
if(!p) printf(" can not create thread ");
while(1)
{
printf("%d" , num ) ;
}
}
the compiler may use a register to store the num variable in the main
thread , so the change to the value by the second thread are ignored .
The volatile modifier is a away of telling the compiler that no
optimization applied to the variable its value be not placed in
register and value may change outside influence during evaluation
# An automatic object declared in a function that
calls setjmp and whose value is-changed between the call to setjmp and
a corresponding call to longjmp
Variables local to functions that call setjmp is most often used. When
an automatic object is declared in a function that calls setjmp, the
compilation system knows that it has to produce code that exactly
matches what the programmer wrote. Therefore, the most recent value for
such an automatic object will always be in memory (not just in a
register) and as such will be guaranteed to be up-to-date when longjmp
is called. Without volatile variable is undefined by the standard
whether the result one see differs with or without optimization simply
reflects that fact
Consider following code
/*Listing 2:Assemply code fragment of above program
produced by cc compile witout volatile keword */
.file"wvol.c"
main:
pushl%ebp
movl%esp翻譯社 %ebp
subl$20翻譯社 %esp
pushl$buf
call_setjmp
addl$16, %esp
testl%eax, %eax
je.L18
subl$8, %esp
pushl$3
pushl$.LC0
callprintf
movl$0, (%esp)
callexit
.p2align 2
.L18:
subl$8翻譯社 %esp
pushl$1
pushl$buf
calllongjmp
char const ptr=(char*)0X15 ;
*ptr access the port consider following code fragment to set the third bit of the output port at periodic intervals
About the author
T i翻譯社 volatile vi ;
Volatile qualifiers can be used to change the behavior of a type. For example,
C語言相關切磋,細究指標(pointer)與參照(reference)}
分別在偵錯版本和release版本運行程式,輸出都是:
i = 10
i = 32
這申明這個樞紐字發揮了它的感化!
printf("i= dn",b);
volatile 指
出
i是隨時可能産生變化的,每次利用它的時候必需從i的位址中讀取,因而編譯器生成的組合說話程式碼會從新從i的位址讀取資料放在b中翻譯而最好化做法是,由
於編譯器發現兩次從i讀數據的程式碼之間的程式碼沒有對i進行過操作,它會自動把前次讀的資料放在b中。而不是重新從i裡面讀。如許以來,若是i是一個寄
存器變數或者默示一個埠資料就輕易出錯,所以說volatile可以保證對非凡位址的不亂存取。
注意,在vc6中,一般偵錯模式沒有進行程式碼最好化,所以這個環節字的感化看不出來翻譯下面經由過程插入組合語言程式碼,測試有沒有volatile關頭字,對程式終究程式碼的影響:
起首,用classwizard建一個win32 console專案,插入一個voltest.cpp檔,輸入下面的程式碼:
#include <stdio.h>
void main()
{
...
//其他代碼,並未明確告知編譯器,對i進行過操作
# An object that is a memory-mapped I/O port
Volatile T * ptr;
T volatile * ptr;
Ptr is a a pointer to a volatile T:
static lon int num ;
void interrupt update(void)
{
++num ;
}
main()
{
long val ;
val = num ;
while(val !=num)
val = num ;
rturn val ;
}
When compilation system execute while statement, the optimizer in compiler may notice that it read the value num once already and that value is still in the register. Instead of re reading the value from memory, compiler may produce code to use the (possibly messed up) value in the register defeating purpose of original C program. Some compiler may optimize entire while loop assuming that since the value of num was just assigned to val , the two must be equal and condition in while statement will therefore always be false .To avoid this 翻譯社you have to declare num to be volatile that warns compilers that certain variables may change because of interrupt routines.
Syntax
When using exact semantics is necessary, volatile
should be used. If you are given a piece of touchy code given as above.
It is a good idea in any case to look the compiler outputting listing
at the assembly language to be sure that compiler produce code that
makes sense.
Use of volatile
}
然後,在偵錯版本模式運行程式,輸出結果以下:
i = 10
i = 32
然後,在release版本模式運行程式,輸出後果以下:
i = 10
i = 10
輸出的結果明明評釋,release模式下,編譯器對程式碼進行了最佳化,第二次沒有輸出准確的 i 值。下面,天成翻譯公司們把 i的宣佈加上volatile關鍵字,看看有什麼轉變:
#include <stdio.h>
void main()
{
}
"Right-Left" Rule}
Console.WriteLine("result = {0}"翻譯社 result);
return;
if (finished) {
}
參考型別翻譯 result = 143;
finished = true;
具有羅列基底型別 byte、sbyte、short、ushort、int 或 uint 的羅列型別翻譯
public static int result;
public static volatile bool finished;
static void Thread2() {
以下類型
}
會產生以下輸出:
這些限制可確保所有的履行緒,將可以或許視察到任何其他履行緒都依其執行遞次履行 Volatile 寫入。遵循此限制的實作其實不需要供應單一整體的 Volatile 寫入遞次,就如同履行的所有履行緒所見。Volatile 物件的型別必需為以下之一:
//下面組合說話語法的作用就是改變記憶體中i的值,然則又不讓編譯器知道
__asm {
Keyword volatile can be placed before or after the data
type in the variable definition. For example following declaration are
identical:
Pointer declaration
volatile pointer to a volatile variable
int volatile * volatile ptr;
volatile can be applied to derived types such as an array type 翻譯社in that case翻譯社 the element is qualified翻譯社 not the array type. When applied to struct types entire contents of the struct become volatile. You can apply the volatile qualifier to the individual members of the struct. Type qualifiers are relevant only when accessing identifiers as l-values in expressions. volatile does not affects the range of values or arithmetic properties of the object.. To declare the item pointed to by the pointer as volatile翻譯社 use a declaration of the form:
C 說話指標的用法volatile T *vptr;
To declare the value of the pointer - that is, the actual
address stored in the pointer - as volatile, use a declaration of the
form:
static volatile long int num ;
With volatile keyword in the declaration the compiler knows that the value of num must b read from memory every time it is referenced.
an 8 bit 翻譯社 memory -mapped I/O port at physical address 0X15 can be declared as
Interrupt service routines often set variables that are tested in main line code. One problem that arises as soon as you use interrupt is that interrupt routines need to communicate with rest of the code .A interrupt may update a variable num that is used in main line of code .An incorrect implementation of this might be:
# An object modified by an interrupt service routine
/* Let T denotes some data type */
typedef volatile T i;
volatile T i;
T volatile i ;
And the following declaration is illegal
#include <setjmp.h>
static jmp_buf buf ;
main( )
{
volatile int b;
b =3 ;
if(setjmp(buf)!=0) {
printf("%d ", b) ;
exit(0);
}
b=5;
longjmp(buf 翻譯社 1) ;
}
volatile variable isn't affected by the optimization. So value of b is after the longjump is the last value variable assigned. Without volatile b may or may not be restored to its last value when the longjmp occurs. For clear understanding assembly listing of above program by cc compiler has been given below.
# An object that is shared between multiple concurrent processes
if two threads/tasks concurrently assign distinct values to the same shared non-volatile variable, a subsequent use of that variable may obtain a value that is not equal to either of the assigned values翻譯社 but some implementation-dependent mixture of the two values. so a global variable references by multiple thread programmers must declare shared variable as volatile.
__asm {int b = i;
printf("i= dn",b);
當要求使用volatile 宣佈的變數的值的時辰,系統總是從新從它地點的記憶體讀取資料,即使它前面的指令方才從該處讀取過資料翻譯而且讀取的資料馬上被保留。
例如:
int a = i;
printf("i= dn",a);
using System;
using System.Threading;
class Test
{
}
static void Main() {
int a = i;
finished = false;
// Run Thread2() in a new thread
new Thread(new ThreadStart(Thread2)).Start();
// Wait for Thread2 to signal that it has a result by setting
// finished to true.
for (;;) {
Volatile as a promise
Ashok K. Pathak a member ( Research Staff ) at Bharat Electronics Limited (CRL) ,
Ghaziabad .He has been developing embedded application for the past five years.
Ashok holds a M.E in computer science and engineering . Ashok recently completed a
book about' "Advanced Test in C and Embedded System Programming" , Published
by BPB 翻譯社 ND .He can be reached at pathak@indiya.com.
延長浏覽:
以下內文出自: http://bluelove1968.pixnet.net/blog/post/222282820-%e3%80%90c-%e8%aa%9e%e8%a8%80%e5%85%a7%22volatile有關各國語文翻譯公證的問題歡迎諮詢天成翻譯公司02-77260931
留言列表