揮発性
1.volatile役割
揮発性の意図がはるかに高速メモリアクセス・レジスタ・ユニットにアクセスするよりも、その「変数」として、一般的に、コンパイラは、アクセス・メモリの最適化を減らすために、しかし、ダーティデータが読むかもしれないので。揮発性宣言は、変数の値を必要に応じて、システムメモリは、再読み込みが指示だけリードデータそこに先行していたとしても、そこからデータを常に。、コンパイラが宣言され、あなたがvalatileを使用しない場合は、正確には、特定のアドレスへの安定したアクセスを提供することができ、変数の宣言、変数のアクセスコードのコンパイラは、もはや最適化されます。このキーワードの出会い、ということです最適化される文。
シンプルプットは、次のとおりです。volatileキーワードは、コンパイラの結果に影響を与え、変数は随時変更される可能性があり、変数揮発性の宣言によって表される、変数の操作に関連する、避けるのミスに最適化されたコンパイルされません
1>コンパイラは任意の最適化を行うことはできません伝えます
プログラム外部で定義された2>を使用して揮発性の変数は、各時刻がメモリから読み出されなければならない、変更されているが、バックアップキャッシュまたはレジスタで再利用することができません。
2.メインシナリオ
1>変数は、ルーチンの変更は揮発追加する必要が割り込みサービス中の他のプログラムによって検出されました。
static int i=0;
int main(void)
{
while (1){
if (i) dosomething();
}
}
/* Interrupt service routine. */
void ISR_2(void)
{
i=1;
}
意図したプログラムは、コンパイラは、メイン関数内部でIを変更しない決定するので、しかし、機能をdoSomethingの主要機能と呼ばれる、発生する割り込みISR_2であり、したがって、レジスタ動作にIから読み出され、一度だけ実行されてもよい、とのそれぞれ第二だけdoSomethingの結果として、レジスタ内部の「私がコピー」の使用が呼ばれることはありませんかどうかを判断します。変数が変更を加えた揮発された場合、コンパイラはこれが(正の実行)に最適化されないことを保証するために、変数を読み取り、書き込みます。この例では、私はこのように説明すべきです。
タスク間で共有2>マルチタスク環境では、符号が揮発性で追加する必要がありますです
2つのスレッドが特定の変数に使用される変数の値が変更される場合には、揮発性で宣言されなければならない、重要な役割は、CPUレジスタにメモリから変数を最適化するコンパイラを防止することです。変数がレジスタにロードされている場合は、2つのスレッド、プログラムの実行中にエラーが発生する可能性があり、メモリで使用する変数、変数のレジスタへの可能性があります。揮発性は、それぞれの時間は、コンパイラの変数の操作は、実際に、メモリからではなく、既存のを使用してのレジスタ値を削除しなければならないことを意味しています
volatile BOOL bStop = FALSE; //bStop 为共享全局变量
(1) 在一个线程中:
while( !bStop ) { ... }
bStop = FALSE;
return;
(2) 在另外一个线程中,要终止上面的线程循环:
bStop = TRUE;
while( bStop );
BSTOPがレジスタに読み込まれているので、あなたが述べた揮発BSTOPを使用しない場合は、上記のスレッドの終了を待っては、このサイクルは、無限ループとなり、レジスタ値BSTOPは揮発性、プログラムの実行と相まって、FALSEになることはありませんたびにメモリからBSTOPの値を読み込むとき、それは死のサイクルではないでしょう。
3>一般に、メモリは、それぞれがその読み取り異なる意味を有することができるので、レジスタはまた、ハードウェアvoliateを追加マッピングしました。
int *output = (unsigned int *)0xff800000;//定义一个IO端口;
int init(void)
{
int i;
for(i=0;i< 10;i++){
*output = i;
}
}
最後に、これは$ 9にだけ出力ポインタであるため、コンパイラの最適化、ナンセンスと考えられ、長い時間のための循環のコンパイラのフロント、最終的な結果に全く影響した後、あなたは最終結果コンパイルされたコードをコンパイルするコンパイラを与えることに相当します。
int init(void)
{
*output = 9;
}
あなたは、この外部デバイスは、その割り当て上記のコードと同じ順序で初期化する必要があります処理する場合、明らかに最適化プロセスは、自分の目標を達成することはできません。一方、あなたは多分一度だけこのアドレスへのあなたのコードを読んで、ポートを繰り返し、コンパイラが最適化され、結果は同じで、それに書かれていますが、繰り返し読み出し動作動作しない場合。しかし、コードの観点からも問題ありません。揮発性の使用の点で、この時点では、変数が経験にこの時間変数を最適化することではない、不安定であることをコンパイラに知らせます。
例えば:
volatile int *output=(volatile unsigned int *)0xff800000;//定义一个I/O端口
3.諸問題
1>パラメータは、いずれかのconstも揮発性であることができますすることができますか?
可能性のある、唯一のステータスレジスタを読んなど。それが予期せず変更される可能性があるのでそれは揮発性です。プログラムはそれを変更しようとするべきではありませんので、それはconstのです。
2>ポインタが揮発することができますか?
割り込みサービスルーチンは、バッファへのポインタを変更することができ。
4.volatile自然:
1>コンパイラの最適化
このスレッドでは、変数を読み取るとき、アクセス速度を向上させるために、コンパイラの最適化変数は、最初のレジスタに読み込まれてもよい;時間後、及び、変数の値をとり、直接レジスタの値から、変数の値は、このスレッドに変更され、また一貫性のために、変数レジスタに新しい値をコピーします。
変数が他のスレッドと他の値に起因する変更された場合、レジスタの値は、変数の値が得られ、それに応じて変更されておらず、実際の値は、一貫性のないアプリケーションを読み取ります。
場合、このレジスタの値を変更することにより、他のスレッド、等に、元の変数の値は、値が得られ、変更されず、可変アプリケーションの実際の値は矛盾読み出します。
2>揮発性は、「生のメモリアドレスへの直接アクセス」より適切な、この解釈「揮発性」として解釈されるべきであるそれは少し誤解を招くでした。
5.次の関数の何が問題になっています。
int square(volatile int *ptr)
{
return *ptr * *ptr;
}
プログラムの目的は、ポインタを返すことである正方形の値にPTRポイント、しかし理由 PTRパラメータ点揮発性のために、コンパイラは、次のようなコードが生成されます。
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}
以来* PTRの値が突然変更され、従って、bは異なっていてもよいしてもよいです。その結果、このコードは、あなたが乗値を期待するよりも、返すことができます!次のように正しいコードは次のとおりです。
long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}
注:揮発性の頻繁な使用は、コードサイズが大きくなると、パフォーマンスが低下する可能性があるので、使用の合理化揮発性。