新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 對Volatile的理解

        對Volatile的理解

        作者: 時間:2016-11-26 來源:網絡 收藏
        Volatile 字面的意思時易變的,不穩定的。

        編譯器優化代碼時,可能會把經常用到的代碼存在Cache里面,然后下一次調用就直接讀取Cache而不是內存,這樣就大大提高了效率。但是問題也隨之而來了。

        本文引用地址:http://www.104case.com/article/201611/322064.htm

        在多線程程序中,如果把一個變量放入Cache后,又有其他線程改變了變量的值,那么本線程是無法知道這個變化的。它可能會直接讀Cache里的數據。但是很不幸,Cache里的數據已經過期了,讀出來的是不合時宜的臟數據。這時就會出現bug。也就是說如果它是一個寄存器變量或者表示一個端口數據就容易出錯,所以說volatile可以保證對特殊地址的穩定訪問。

        用Volatile聲明變量可以解決這個問題。用Volatile聲明的變量就相當于告訴編譯器,我不要把這個變量寫Cache,因為這個變量是可能發生改變的。

        如果一個變量的值可能會被程序操作之外的其它操作所改變,那么你必需用volatile 聲明。在嵌入式系統中其它操作是:中斷服務程序的操作、硬件動作的操作等,下面列舉了需要加volatile 聲明的情況。

        1、中斷服務程序中修改的供其它程序檢測的變量需要加volatile;

        2、多任務環境下各任務間共享的標志應該加volatile;

        3、存儲器映射的硬件寄存器通常也要加volatile說明,因為每次對它的讀寫都可能由不同意義;

        用volatile聲明的變量是不會被編譯器優化掉的

        例如:

        #definePortA( * ( volatile unsignedint * )0x0000 )

        這樣 PortA 成為一個地址在0x0000的unsigned int類型變量。這個定義看起來很復雜,其實它也可以分解成幾個很簡單的部分來看。 ( volatile unsignedint * )是C語言中的強制類型轉換,它的作用是把0x0000這個純粹的十六進制數轉換成為一個(地址)指針,其中volatile并不是必要的,它只是告訴編譯器,這個值與外界環境有關,不要對它優化。接下來在外面又加了一個*號,就表示0x0000內存單元中的內容了。經過這個宏定義之后,PortA就被可以做為一個普通的變量來操作,所有出現PortA的地方編譯的時候都被替換成( * ( volatile unsignedint * )0x0000 ),外面一層括號是為了保證里面的操作不會因為運算符優先級或者其它不可預測的原因被改變而無法得到預期的結果。

        PORTA做為一個輸入端口,其值是由外部設備決定的,由于外部設備的變化是隨機的,因此第一次讀取的值和第二次讀取的值很可能不同,所以我們把它聲明為volatile變量。

        a = PORTA;

        a = PORTA;

        由于PORTA是用volatile聲明的變量,編譯器不會把它優化成一句,而如果不是volatile聲明的編譯器就會將第二句優化掉,從而程序將會忽略輸入端口的變化。

        通常把嵌入式設備的所有外圍器件寄存器都聲明為volatile的。

        這種定義方法適合所有的C編譯器,可移植性好,但PortA并不是一個真正的變量,只是一個宏名,當你調試一個程序的時候,無法在調試窗口觀察它的值。另外連接器也失去了靈活性,它得防止其它變量跟此變量沖突。


        評論


        技術專區

        關閉
        主站蜘蛛池模板: 南川市| 南康市| 石河子市| 晋江市| 呼图壁县| 老河口市| 繁峙县| 灵川县| 石屏县| 商洛市| 长阳| 灵武市| 宜兰县| 静乐县| 济宁市| 长寿区| 石柱| 新竹县| 博乐市| 江孜县| 武宁县| 土默特左旗| 长丰县| 竹北市| 兴安县| 长子县| 鄯善县| 怀化市| 铜川市| 高密市| 贵定县| 衡水市| 彭泽县| 湘阴县| 错那县| 皮山县| 黄陵县| 区。| 东乡族自治县| 霞浦县| 六安市|