Linux下的4G虛擬位址記憶體分布

2021-09-25 09:52:07 字數 1795 閱讀 8986

開門見山

在編譯執行過程中,我們需要將我們的程式儲存到記憶體中才能調取執行,但是記憶體是有限的,不可能將所有的程序都放在記憶體中去,所以會給程序分配乙個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 棧空間 特點是由系統管理,先進後出,裡面放了區域性變數 函式形參 自動變數。...