虛擬位址空間以及編譯模式

2021-08-02 18:09:18 字數 3539 閱讀 5666

所謂虛擬位址空間,就是程式可以使用的虛擬位址的有效範圍。

虛擬位址和實體地址的對映關係由作業系統決定,相應地,虛擬位址空間的大小也由作業系統決定,但還會受到編譯模式的影響。

這節我們先講解cpu,再講解編譯模式,讓大家了解編譯器是如何配合cpu來提高程式執行速度的。

cpu是計算機的核心,決定了計算機的資料處理能力和定址能力,也即決定了計算機的效能。cpu一次(乙個時鐘內)能處理的資料的大小由暫存器的位數和資料匯流排的寬度(也即有多少根資料匯流排)決定,我們通常所說的多少位的cpu,除了可以理解為暫存器的位數,也可以理解資料匯流排的寬度,通常情況下它們是相等的。

資料匯流排位於主機板之上,不在cpu中,也不由cpu決定,嚴格來講,這裡應該說cpu能夠支援的資料匯流排的最大根數,也即能夠支援的最大資料處理能力,為了表達方便,本文才使用「cpu的資料匯流排」這一說法。
資料匯流排和主頻都是cpu的重要指標:資料匯流排決定了cpu單次的資料處理能力,主頻決定了cpu單位時間內的資料處理次數,它們的乘積就是cpu單位時間內的資料處理量。

我們常常聽說,cpu主頻在計算機的發展過程中飛速提公升,從最初的幾十 khz,到後來的幾百 mhz,再到現在的 4ghz,終於因為矽晶體的物理特性很難再提公升,只能向多核方向發展。在這個過程中,cpu的資料匯流排寬度也在成倍增長,從早期的8位、16位,到後來的32位,現在我們計算機大部分都在使用64位cpu。

需要注意的是,資料匯流排和位址匯流排不是一回事,資料匯流排用於在cpu和記憶體之間傳輸資料,位址匯流排用於在記憶體上定位資料,它們之間沒有必然的聯絡,寬度並不一定相等。實際情況是,位址匯流排的寬度往往隨著資料匯流排的寬度而增長,以訪問更大的記憶體。

1) 16位cpu

早期的cpu是16位的,一次能處理 16bit(2個位元組)的資料。這個時候計算機產業還處在早期,個人電腦也沒有進入千家萬戶,也沒有提出虛擬位址的概念,程式還是直接執行在物理記憶體上,作業系統對記憶體的管理非常簡陋,程式設計師輕易就能編寫乙個惡意程式去修改其他程式的記憶體。

學過彙編的同學應該知道,典型的16位處理器是 intel 8086,它的資料匯流排有16根,位址匯流排有20根,定址能力為 2^20 = 1mb。

2) 32位cpu

隨著計算機產業的進步,出現了32位的cpu,一次能處理 32bit(4個位元組)的資料。這個時候就提出了虛擬位址的概念,並被應用到cpu和作業系統中,由它們共同完成虛擬位址和實體地址的對映,這使得程式編寫更加容易,執行更加安全。

典型的32位處理器是 intel 的 80386 和 intel pentium 4(奔騰4):80386 的資料匯流排和位址匯流排寬度都是32位,定址能力達4gb;pentium 4的位址匯流排寬度是36位,理論定址能力達64gb。

3) 64位cpu

現代計算機都使用64位的cpu,它們一次能處理64bit(8個位元組)的資料。典型的64位處理器是 intel 的 core i3、i5、i7 等,它們的位址匯流排寬度為 40~50 位左右。64位cpu的出現使個人電腦再次發生了質的飛躍。

cpu支援的物理記憶體只是理論上的資料,實際應用中還會受到作業系統的限制,例如,win7  64位家庭版最大僅支援8gb或16gb的物理記憶體,win7 64位專業版或企業版能夠支援到192gb的物理記憶體。

windows server 2003 資料中心版專為大型企業或國家機構而設計,可以處理海量資料,分為32位版和64位版,32位版最高支援512gb的物理記憶體,這顯然超出了32位cpu的定址能力,可以通過兩次定址來實現。

為了相容不同的平台,現代編譯器大都提供兩種編譯模式:32位模式和64位模式。

32位編譯模式

在32位模式下,乙個指標或位址占用4個位元組的記憶體,共有32位,理論上能夠訪問的虛擬記憶體空間大小為 2^32 = 0x100000000 bytes,即4gb,有效虛擬位址範圍是 0 ~ 0xffffffff。 

也就是說,對於32位的編譯模式,不管實際物理記憶體有多大,程式能夠訪問的有效虛擬位址空間的範圍就是0 ~ 0xffffffff,也即虛擬位址空間的大小是 4gb。換句話說,程式能夠使用的最大記憶體為 4gb,跟物理記憶體沒有關係。

如果程式需要的記憶體大於物理記憶體,或者記憶體中剩餘的空間不足以容納當前程式,那麼作業系統會將記憶體中暫時用不到的一部分資料寫入到磁碟,等需要的時候再讀取回來,這在《

載入記憶體,讓程式執行起來

》中已經講到。而我們的程式只管使用 4gb 的記憶體,不用關心硬體資源夠不夠。

如果物理記憶體大於 4gb,例如目前很多pc機都配備了8gb的記憶體,那麼程式也無能為力,它只能夠使用其中的 4gb。

64位編譯模式

在64位編譯模式下,乙個指標或位址占用8個位元組的記憶體,共有64位,理論上能夠訪問的虛擬記憶體空間大小為 2^64。這是乙個很大的值,幾乎是無限的,就目前的技術來講,不但物理記憶體不可能達到這麼大,cpu的定址能力也沒有這麼大,實現64位長的虛擬位址只會增加系統的複雜度和位址轉換的成本,帶不來任何好處,

所以 windows 和 linux 都對虛擬位址進行了限制,僅使用虛擬位址的低48位(6個位元組),總的虛擬位址空間大小為 2^48 = 256tb。

需要注意的是:

目前計算機可以說已經進入了64位的時代,之所以還要提供32位編譯模式,是為了相容一些老的硬體平台和作業系統,或者某些場合下32位的環境已經足夠,使用64位環境會增大成本,例如嵌入式系統、微控制器、工控等。

這裡所說的32位環境是指:

32位的cpu + 32位的作業系統 + 32位的程式。

另外需要說明的是,32位環境擁有非常經典的設計,易於理解,適合教學,現有的很多資料都是以32位環境為基礎進行講解的。本教程也是如此,除非特別指明,否則都是針對32位環境。相比於32位環境,64位環境的設計思路並沒有發生質的變化,理解了32環境很容易向64位環境遷移。

以 vs2010 為例,建立工程後預設是32位的,如下圖所示:

「win32」表示32位編譯模式。如果要以64位的方式編譯,就需要新增編譯模式,如下圖所示:

選擇「配置管理器」,彈出如下的對話方塊:

在「活動解決方案平台」下選擇「新建」,彈出下面的對話方塊:

在下拉列表中選擇「x64」,即可新增64位編譯模式。現在,我們就可以在兩種編譯模式之間進行切換了:

將下面的**複製到原始檔中:

#include

#include

int a;

intmain

()

在 win32 編譯模式下的結果:

0xb715c, 4

在 x64 編譯模式下的結果:

0x3ff39740, 8

虛擬位址空間

當處理器讀或寫入記憶體位置時,它會使用虛擬位址。作為讀或寫操作的一部分,處理器將虛擬位址轉換為實體地址。通過虛擬位址訪問記憶體有以下優勢 程序可用的虛擬位址範圍稱為該程序的 虛擬位址空間 每個使用者模式程序都有其各自的專用虛擬位址空間。對於 32 位程序,虛擬位址空間通常為 2 gb,範圍從 0x0...

虛擬位址空間

14 共 14 對本文的評價是有幫助 評價此主題 程序可用的虛擬位址範圍稱為該程序的 虛擬位址空間 每個使用者模式程序都有其各自的專用虛擬位址空間。對於 32 位程序,虛擬位址空間通常為 2 gb,範圍從 0x00000000 至 0x7fffffff。對於 64 位程序,虛擬位址空間為 8 tb,...

虛擬位址空間

1 text 段 存放程式執行的一塊記憶體區域,此區域大小在執行之前就已經確定下來了。2 data資料段 全域性初始化資料區 靜態資料區 只初始化一次,指用來存放程式中已初始化的全域性變數的一塊記憶體區域 已經初始化的全域性變數 靜態變數和常量 3 bss未初始化資料區 用來存放程式中未初始化的全域...