任何程式語言最終產生的結果為:指令 + 資料。我們寫完**在編譯鏈結產生可執行檔案後,可執行檔案在磁碟上,執行時需要由磁碟載入到記憶體當中,那載入了哪些東西呢?它們是如何存放的?我們平常寫**時,資料和指令再執行時放在記憶體的**呢?讓我們帶著這一串疑問去了解一下程序的虛擬位址空間記憶體劃分與布局吧。
假如使用的是在x86體系下32位的作業系統下的c++,系統會給當前程序分配乙個232大小的一塊空間,即4g。這塊空間就是程序的虛擬位址空間。
虛擬位址空間: 虛擬位址空間預設被劃分為兩部分,使用者空間(3g)與核心空間(1g)。每乙個程序的使用者空間是私有的,但是核心空間是共享的。其空間布局如圖所示:
1.使用者空間:0x00000000——0xc0000000
①預留段:不能夠訪問,從0x00000000——0x08048000這段位址不能訪問。例如:我們訪問空指標時會報錯,此時位址為0,不能訪問。
②.text段:**段,指令執行時放在該段。
③.rodata段:唯讀資料段,只允許讀。
例如:我們在函式裡定義了下面這條語句,char *p為區域性變數指標,p在棧上,p指向的常量字串就在.rodata段,只能讀不允許修改。
④.data段:存放初始化了的或初始化的值不為0的資料段。
⑤.bss段:未初始化的或初始化的值為0的資料段。
⑨命令列引數和環境變數:存放命令列引數與環境變數。
2.核心空間:0xc0000000——0xffffffff
①zone_dma:範圍是0~16m,該區域的物理頁面專門供i/o裝置的dma使用。之所以需要單獨管理dma的物理頁面,是因為dma使用實體地址訪問記憶體,不經過mmu,並且需要連續的緩衝區,所以為了能夠提供物理上連續的緩衝區,必須從實體地址空間專門劃分一段區域用於dma。
②zone_normal:範圍是16m~896m,該區域的物理頁面是核心能夠直接使用的。
③zone_highmem:範圍是896m~結束,該區域即為高階記憶體,對映高位址記憶體做位址對映時使用,核心不能直接使用。
明白了上面虛擬位址空間位址的劃分與功能之後,我們來練習一道題吧。如下**:我們在main外定義了三個不同的全域性變數、三個不同靜態全域性變數;在main中定義了三個不同的區域性變數,三個不同的靜態區域性變數。那麼它們分別儲存在**呢?
#include
using namespace std;
int gdata1 =10;
int gdata2 =0;
int gdata3;
static
int gdata4 =11;
static
int gdata5 =0;
static
int gdata6;
intmain()
沒錯,聰明的你一定知道了答案:
函式呼叫棧的流程是什麼樣的呢?
首先我們來看這樣一段非常簡單的**:
#include
using namespace std;
intsum
(int a,
int b)
intmain()
為了更深入的了解它,我們這裡產生了兩個問題。
問題1:main函式呼叫sum,sum執行完後,怎麼知道回到哪個函式中去?例如這裡main呼叫sum函式,sum函式執行完後怎麼知道要返回main函式中去?
問題2:sum函式執行完回到main以後,怎麼知道從哪一行指令繼續執行?
我們函式使用時要在棧幀上開闢空間,形參變數的記憶體開闢是在呼叫方就開闢好的,呼叫方函式實參進行壓棧。從該圖中即可解決上面2個問題。
函式呼叫過程:執行順序為1,2,3,4,5。
棧幀變化:這裡只給出了最後的樣子。
C 虛擬位址空間
一 引言 在計算機中,每台裝置以及程序都被分配乙個位址空間。位址空間包括物理空間以及虛擬空間。如果將實體地址暴露給程序,使用者就很容易破壞作業系統,從而使系統停止 另外隨著程序數量和體積的增長,核心空間變得越來越不夠用,從而引入虛擬位址空間。實體地址 physical address 放在定址匯流排...
虛擬位址空間
當處理器讀或寫入記憶體位置時,它會使用虛擬位址。作為讀或寫操作的一部分,處理器將虛擬位址轉換為實體地址。通過虛擬位址訪問記憶體有以下優勢 程序可用的虛擬位址範圍稱為該程序的 虛擬位址空間 每個使用者模式程序都有其各自的專用虛擬位址空間。對於 32 位程序,虛擬位址空間通常為 2 gb,範圍從 0x0...
虛擬位址空間
14 共 14 對本文的評價是有幫助 評價此主題 程序可用的虛擬位址範圍稱為該程序的 虛擬位址空間 每個使用者模式程序都有其各自的專用虛擬位址空間。對於 32 位程序,虛擬位址空間通常為 2 gb,範圍從 0x00000000 至 0x7fffffff。對於 64 位程序,虛擬位址空間為 8 tb,...