開門見山
在編譯執行過程中,我們需要將我們的程式儲存到記憶體中才能調取執行,但是記憶體是有限的,不可能將所有的程序都放在記憶體中去,所以會給程序分配乙個4g的虛擬位址空間儲存資料,在程序執行時在對映到記憶體中去。
一般情況下
windows下記憶體分布情況為 使用者態:核心態是 1:1
而在linux下記憶體的分布情況為 使用者態:核心態是 3:1
下面給出4g虛擬位址記憶體分布圖
下面分析從位址到高位址 各段的意義
首先是3g使用者態空間
保留區保留區通常大小為128m,,我們通常將申請的臨時指標變數初始化時置為null,可以防止後續無意使用這個指標出錯,因為null == 0x0,將其指標指向0x0這個位址時,因為0x0這個位址屬於保留區,沒有訪問許可權的。
.text段
指令段:通常是指用來存放程式執行**的一塊記憶體區域。這部分區域的大小在程式執行前就已經確定,並且記憶體區域通常屬於唯讀, 某些架構也允許**段為可寫,即允許修改程式。在**段中,也有可能包含一些唯讀的常數變數,例如字串常量等。
.data段
data段一般存放程式中已被初始化或者初始化不為0的全域性變數和靜態變數,常量也存在資料段中。資料段屬於靜態記憶體分配。
.bss段
bss段一般存放的是程式中未被初始化或初始化為0的全域性變數。在程式載入時,由核心清零。
題外話(為什麼有了data段還有設計bss段)
(1)bss段不占用物理檔案尺寸,但占用記憶體空間;資料段占用物理檔案,也占用記憶體空間。所以有兩個資料段節省檔案空間。
對於大型陣列如int ar0[10000] = 和int ar1[10000],ar1放在bss段,只記錄共有10000*4個位元組需要初始化為0,而不是像ar0那樣記錄每個資料1、2、3…,此時bss為目標檔案所節省的磁碟空間相當可觀。
(2)當程式讀取資料段的資料時,系統會出發缺頁故障,從而分配相應的物理記憶體;當程式讀取bss段的資料時,核心會將其轉到乙個全零頁面,不會發生缺頁故障,也不會為其分配相應的物理記憶體。
5. 堆
一般需要手動申請,手動釋放(os也有可能**),否則容易發生記憶體洩漏
6. 共享庫
在編寫程式時,會依靠其他人已經寫好的許多**來執行例程或特殊功能。 這些**儲存在共享庫中使用它們,需要將它們與自己的**相鏈結,無論是在構建程式時還是在執行程式時。
7. 棧
由編譯器自動分配釋放
棧主要有三個用途:
①函式的返回位址(以便從被呼叫者返回)和引數
②存放臨時變數:包括函式的非靜態區域性變數以及編譯器自動生成的其他臨時變數
③儲存上下文:包括在函式呼叫前後需要保持不變的暫存器
8. 命令列引數
主函式main中有三個引數
void main(int argc,char *ar**,char*envp)
其中argc表示的命令列引數個數,預設情況下為1
ar**表示就是ar**引數內容,ar**[0]為命令列中可執行程式名本身,ar**[1]為命令列中第二個引數的內容
9. 環境變數
envp表示的就是環境變數
其次是1g的核心態空間
作用:linux 作業系統和驅動程式執行在核心空間
zone_dma 16mb
zone_normal 892m
zone_highmen 128m
用於在核心中對映高於1g的物理記憶體時使用。64位系統則沒有該段(64位作業系統給核心空間分配的記憶體達到512g)。
4G虛擬位址空間
在linux系統中,使用者空間和核心空間所佔的比例為3 1 在windows系統中,使用者空間和核心空間所佔的比例為2 2 下面以linux系統為例 text 指令段,也叫 段,區域性變數也是指令,但區域性變數儲存在棧上,當 執行時才在棧中預留好的區域中開闢。data 資料段儲存 中的各種資料,包括...
4G虛擬位址空間布局
一 其中,使用者程序部分分段儲存內容如下表所示 按位址遞增順序 名稱儲存內容 段 text 可執行 字串字面值 唯讀變數 資料段 data 已初始化且初始值為非0的全域性變數和靜態區域性變數 bss段 未初始化或初始值為0的全域性變數和靜態區域性變數 棧區域性變數 函式引數 返回位址等 堆動態分配的...
程序的虛擬位址空間4G劃分
當乙個程 序執行的時候 而這4g也劃分成了兩大塊。第一塊1g要分給核心,我們使用者是看不見也進不去的。第二塊3g是給使用者使用的。就像地拿到手了,還要蓋房裝修,我們使用者拿到這3g也要做同樣的事,這3g也要分成好幾塊。3g 棧空間 特點是由系統管理,先進後出,裡面放了區域性變數 函式形參 自動變數。...