linux中使用volatile(附加變數型別)

2021-08-19 23:34:31 字數 2517 閱讀 2874

(1)自動變數就是在函式內部定義的變數,只在內部有效

(2)所以允許其他函式定義相同的變數

(3)他們都有自己的區域性,沒有連線性

(4)自動變數分配記憶體就壓棧,函式返回時退棧

(5)一般不作專門說明的區域性變數,均是自動變數,比如static說明

(6)自動變數使用棧機制使用記憶體

(1)記憶體中的位置:靜態儲存區

(2)未經初始化的全域性靜態變數會被程式自動初始化為0(自動物件的值是任意的,除非他被顯示初始化)

(3)當static用來修飾區域性變數的時候,它就改變了區域性變數的儲存位置,從原來的棧中存放改為靜態儲存區,但是區域性靜態變數在離開作用域之後,並沒有被銷毀,而是仍然駐留在記憶體當中,值也保留,等程式下次再去執行這個函式,去使用它

(4)當static用來修飾全域性變數的時候,它就改變了全域性變數的作用域(在宣告他的檔案之外是不可見的),但是沒有改變它的存放位置,還是在靜態儲存區中。

(1)不會被其他檔案所訪問,修改

(2)其他檔案中可以使用相同名字的變數,不會發生衝突

(3)記憶體中的位置:靜態儲存區(靜態儲存區在整個程式執行期間都存在)

(4)未經初始化的全域性靜態變數會被程式自動初始化為0(自動物件的值是任意的,除非他被顯示初始化)

(1)其他檔案中可以定義相同名字的函式,不會發生衝突

(2)靜態函式不能被其他檔案所用。

(1)c語言中可以使用暫存器來優化程式效能,將乙個常用變數宣告成暫存器變數:resgister int i;如果可能的話,編譯器會為他分配乙個單獨額暫存器,那函式執行期間對這個變數的操作全是對暫存器操作,就不用頻繁去訪問記憶體,讀來讀去,自然提高了程式的效能

(1)表示變數是易失的,易變的

(2)強制訪問記憶體操作,防止編譯器去優化,告訴編譯器每次必須去記憶體中取值,而不是暫存器或快取中

前言:乙個定義為volatile的變數是說這變數可能會被意想不到地改變,這樣,編譯器就不會去假設這個變數的值了。精確地說就是,優化器在用到這個變數時必須每次都小心地重新讀取這個變數的值,而不是使用儲存在暫存器裡的備份

(1)volatile關鍵字是一種型別修飾符,用它宣告的型別變數表示可以被某些編譯器未知的因素更改,比如:作業系統、硬體或者其它執行緒等。遇到這個關鍵字宣告的變數,編譯器對訪問該變數的**就不再進行優化,從而可以提供對特殊位址的穩定訪問。 

(2)volatile 指出 i是隨時可能發生變化的,每次使用它的時候必須從i的位址中讀取,因而編譯器生成的彙編**會重新從i的位址讀取資料放在b中。而優化做法是,由於編譯器發現兩次從i讀資料的**之間的**沒有對i進行過操作,它會自動把上次讀的資料放在b中。而不是重新從i裡面讀。這樣以來,如果i是乙個暫存器變數或者表示乙個埠資料就容易出錯,所以說volatile可以保證對特殊位址的穩定訪問。

(3)volatile對應的變數可能在你的程式本身不知道的情況下發生改變   對於volatile型別的變數,系統每次用到他的時候都是直接從對應的記憶體當中提取,而不會利用cache當中的原有數值,以適應它的未知何時會發生的變化,系統對這種變數的處理不會做優化——顯然也是因為它的數值隨時都可能變化的情況。 

(1)並行裝置的硬體暫存器(如:狀態暫存器) 

(2)乙個中斷服務子程式中會訪問到的非自動變數(non-automatic variables) 

(3)多執行緒應用中被幾個任務共享的變數 

(1)乙個引數既可以是const還可以是volatile嗎?

解釋:乙個例子是唯讀的狀態暫存器。它是volatile因為它可能被意想不到地改變,是內部機制變化造成,而不是你的程式改變了它,而是作業系統把你的程式轉成組合語言時編譯器另外加的彙編改變了它,它是const因為你寫的程式部分不應該試圖去修改它

(2)乙個指標可以是volatile嗎?

解釋:可以,儘管不常見,不如在中斷服務子程式修改乙個指向乙個buffer的指標,防止編譯器去優化,告訴編譯器每次必須去記憶體中取值,而不是暫存器或快取中

(3)多執行緒應用總被幾個任務共享的變數

解釋:volatile對應的變數可能在你的程式本身不知道的情況下發生改變 。比如多執行緒的程式,共同訪問的記憶體當中,多個程式都可以操縱這個變數 ,你自己的程式,是無法判定合適這個變數會發生變化  ,就像作業系統對執行緒的排程,內部排程機制在處理,所以有些變數程式本身是無法**的

總結:   (1)編譯器只會去看兩次從i讀資料的**之間的**沒有對i進行過操作,但是在內部對資料處理過程是很複雜,volatile會改變**生成的彙編**,就是優化彙編**,和不優化的彙編**。如果i是乙個暫存器變數或者表示乙個埠資料,他可能被內部執行緒排程機制,突然使用了這個暫存器把這個暫存器改變了,有些彙編語句改變記憶體的值時,編譯器並不知道,編譯器看你的程式沒有改變值,預設優化了,所以加了volatile就不會優化了

(2)在vc6中,一般除錯模式沒有進行**優化,所以這個關鍵字的作用看不出來 ,在嵌入式中不一樣,

示例**:

#define    rreg    (*(volatile unsigned int *)0x0fef0e00)

解引用      強制型別轉換             實際暫存器位址

rreg  =  0xffff0000 對暫存器直接賦值,rreg是解引用後的變數

在Linux中使用執行緒

我並不假定你會使用linux的執行緒,所以在這裡就簡單的介紹一下。如果你之前有過多執行緒方面的程式設計經驗,完全可以忽略本文的內容,因為它非常的初級。首先說明一下,在linux編寫多執行緒程式需要包含標頭檔案pthread.h。也就是說你在任何採用多執行緒設計的程式中都會看到類似這樣的 1 incl...

Linux中使用gdb dump記憶體

在應急響應中,我們往往會有dump出某一塊記憶體下來進行分析的必要。今天要講的是利用gdb命令dump出sshd程序的記憶體。按照 linux 系統的設計哲學,核心只提供dump記憶體的機制,使用者想要dump什麼樣的記憶體,dump多少記憶體是屬於策略問題,由使用者來決定。在真實的使用場景中,主要...

Linux系統中使用NCBI BLAST

實操 linux系統中使用ncbi blast mp.weixin.qq.com 全基因組基因家族成員鑑定與分析中,第一步就需要通過資料庫檢索進而鑑定成員,基於此方可進行諸如構建進化樹 保守domain和motif分析 基因結構分析等一系列生物資訊學 分析以及轉錄組或螢光定量表達分析 微生物測序資料...