volatile 告訴編譯器:該變數可能在程式不可見的情況下被修改(硬體、中斷、其他執行緒),每次存取必須直接讀寫記憶體,禁止寄存器快取與相關優化。
volatile short flag = 0;
void test(void) {
do_something();
while (flag == 0); // 若無 volatile,編譯器可能將 flag 載入暫存器 → 死循環
do_next();
}
中斷服務程式修改 flag = 1,主迴圈必須看到更新值。
volatile int i=1; if(i>0)... 不會被優化為無條件真volatile ≠ 原子性
x86 需LOCK前綴,RISC 需LL/SC或原子指令。
jiffies++非原子,需atomic_inc()或鎖保護。
現代 CPU 具備亂序執行、Cache 一致性協定。編譯器優化包含:
GCC 內聯組語中 "memory" clobber 相當於編譯器層面的完整記憶體屏障:
asm volatile("" ::: "memory"); // 編譯器屏障:強制將暫存器寫回記憶體,後續重新讀取
Linux 核心提供 barrier() 實現相同效果。
| 特性 | volatile 變數 | "memory" clobber |
|---|---|---|
| 範圍 | 單一變數 | 所有可見記憶體 |
| 適用處 | 變數宣告 | 內聯組語區塊 |
| 硬體屏障 | 無 | 無(僅編譯器) |