linux 程序在記憶體中的布局

2021-06-26 13:12:18 字數 1898 閱讀 1472

先從(linux平台下)虛擬記憶體管理說起,

寫c程式時,我們經常會列印乙個指標位址,說這個指標指向某某記憶體位址.可這些位址是真實物理記憶體位址嗎?不是!這些只是虛擬記憶體位址.

當乙個c程式調入記憶體開始執行後,在記憶體中就會產生乙個程序.而在多工作業系統中每個程序都擁有一片屬於自己的記憶體空間(記憶體沙盤),這個沙盤就是虛擬位址空間,在32位下是乙個4gb的大小的位址塊,這些虛擬位址通過頁表對映到物理記憶體.

但系統並不會真的一下分配給每乙個程序4gb的物理記憶體空間的對映=  =(不現實啊),這4gb只能是說邏輯位址,它會隨著程序的真實需要自動擴充套件對映到物理記憶體空間,最大到4gb.

4gb(位址0-0xffffffff)其中1gb必須保留給系統核心(這是linux平台下),也就是說程序自身只能擁有3gb的位址(0-0xc0000000),如圖

我自己畫的=  =:

**區:

程式(函式)**所在,由編譯而得到的二進位制**被載入至此.**區是唯讀的!有執行許可權.**區一般都從0x08048000位址開始(linux下).值得注意的是,字串字面值(如"hello world")就儲存在這個區.

資料段bss段:合稱靜態區(全域性區),用來儲存靜態(全域性)變數.區別是 前者(資料段)儲存的是已初始化的靜態(全域性)變數,可讀寫. 

後者(bss段)儲存的是未初始化的靜態(全域性)變數,可讀寫.

:自由儲存區.不像全域性變數和區域性變數的生命週期被嚴格定義,堆區的記憶體分配和釋放是由程式設計師所控制的.申請方式:c中是malloc函式,c++中是new識別符號.

:由系統自動分配和釋放.儲存區域性(自動)變數. 一般說的堆疊,其實是指 棧!

另外,值得注意的是,是由低位址向高位址分配空間;卻是由高位址向低位址分配空間.

下面這段**進一步說明c程式中各資料的記憶體布局:

#include #include int i1 = 10; //靜態全域性區(data段)

int i2; //靜態全域性區(bss段)

static int i3 = 30; //靜態全域性區(data段)

const int i4 = 40; //**區!!!

void fun(int i5) //棧區

int main(void)

(gcc編譯)程式輸出:

至此,從位址大小比較可以看出

1)靜態(static)全域性變數靜態(static)區域性變數都在 靜態全域性區.

2)全域性常量i4儲存在**區,而區域性常量i8儲存在棧區.

所以最上面的問題是,**區唯讀,修改全域性常量會引發執行時段錯誤,而區域性常量是可以成功賦值修改的.

3)字串字面值在**區(所以不可修改),但是字元指標str1在棧區;字元陣列str2在棧區(所以可以修改).

最後要說,上述是linux下的虛擬記憶體布局順序,windows下會有所不同.但是對於c程式中資料應該儲存在**都是一致的.

Unix Linux程序在記憶體中的布局

對於linux作業系統之上的程式而言,其執行的程序所使用的記憶體位址都是虛擬位址,是mmu經過對映後的位址,我們這裡所談及的記憶體也是虛擬記憶體,而不是物理記憶體。我們將編寫好的程式經過gcc編譯得到乙個可執行的檔案,然後將其執行起來,通過檢視程序的命令得到程序id ps aux 在得到程序id之後...

乙個程序在記憶體中的布局

對於乙個完整的程式,在記憶體中分布情況如下圖 值得一提的是 在c 中struct存放在棧區,class存放在堆區,所以一般struct要比class要快的。堆和棧的比較表 僅針對c 棧 stack 堆 heap 申請方式 由os自動分配。例如在函式宣告乙個區域性變數int b os自動在棧中為b開闢...

乙個程序在記憶體中的布局

對於乙個完整的程式,在記憶體中分布情況如下圖 值得一提的是 在c 中 struct 存放在棧區,class 存放在堆區,所以一般 struct 要比class 要快的。堆和棧的比較表 僅針對c 棧 stack 堆 heap 申請方式 由 os自動分配。例如在函式宣告乙個區域性變數 int b os ...