5 2 1 程序的記憶體布局

2021-08-16 02:58:20 字數 2256 閱讀 1708

《c++應用程式效能優化(第2版)》第5章作業系統的記憶體管理,本章前一部分著重介紹windows的虛擬記憶體管理機制,後一部分則簡要介紹linux的虛擬記憶體管理機制。本節為大家介紹程序的記憶體布局。

2010-06-03 11:56

收藏 分享

5.2  linux記憶體管理機制

linux的記憶體管理主要由兩個部分組成,乙個部分負責物理記憶體的申請與釋放,物理記憶體的申請與釋放最小單位與windows一樣,都是以"頁"為單位,在ia32中頁的大小是4 kb;另外乙個部分負責處理虛擬記憶體,虛擬記憶體的操作主要包括虛擬位址空間與實際儲存空間的對映,物理記憶體頁與硬碟頁之間的置換等,下面各節分別介紹這幾個方面的內容。

5.2.1  程序的記憶體布局

乙個32位linux程序的位址空間為4 gb,與windows類似,這個4 gb空間並不能全部被乙個linux程序的使用者空間**使用,而是有一部分留給了核心。但與windows不同,linux中4 gb的高位1 gb空間留給了核心,低位的3 gb由程序使用者**使用,如圖5-7所示。

0x00000000~0xbfffffff這一3 gb區域為使用者位址空間,而上面的0xc0000000 ~ 0xffffffff這一1 gb區域保留給核心使用。使用者位址空間進一步被分成程式**區、資料區(包括初始化資料區data和未初始化資料區bss)、堆和棧。程式**區佔據最底端,緊接著往上為資料區,先是初始化資料區,然後是未初始化資料區。**區中存放應用程式的機器**,執行過程中**不能被修改,因此**區記憶體為唯讀,且大小固定。資料區中存放了應用程式中的全域性資料,靜態資料和一些常量字串等。資料區的大小也是固定的。

圖5-7  乙個32位linux程序的位址空間

如圖5-8所示,除了**區,初始化資料區和未初始化資料區之外,還有兩個動態增長和縮減的區域即堆和棧。

堆從未初始化資料區開始,向上端動態增長,增長過程中虛擬位址值變大;而棧則從高位位址開始,向下端動態增長,虛擬位址值變小。

堆是應用程式在執行過程中動態申請的記憶體空間,如開發人員通過malloc/new需要動態生成物件或者開闢記憶體空間時,最終會呼叫系統呼叫brk來動態調整資料區的大小。當這些動態記憶體區域使用完畢,需要開發人員明確使用相應的free/delete釋放這些記憶體空間。free/delete最終也會呼叫到brk調整資料區的大小。

圖5-8  堆和棧

棧與堆有明顯的區別,棧用來存放函式的傳入引數、臨時變數,以及返回位址等資料。這些資料不需要通過malloc/new來為之開闢記憶體空間,而且其增長與縮減是因為函式的呼叫與返回,而不必開發人員的額外操作。堆空間的維護不需要開發人員的參與,而且也沒有記憶體洩漏的危險。

初始化資料區和未初始化資料區還有一些值得注意的事情,初始化資料區存放的是那些在編譯期就能夠知道由程式設定初始值的全域性變數及靜態變數等。這些初始值必須儲存在最終生成的二進位制檔案中,並且在程式執行時會原封不動地將這個區域對映到程序的初始化資料區域。當程式宣告n個這樣的初始化資料,且其空間佔據m大小,那麼在二進位制檔案中,就會開闢m大小的區域。即依次存放n個資料,且每個都設定了相應的初始值。當程式執行時,這塊區域就會原封不動地對映到該對應程序的"初始化資料區"。"原封不動"意味著在二進位制檔案中這塊區域的大小與程序虛擬位址空間中一樣大,而且排列和對應位址的值也一樣。

但未初始化資料區則不如此,如果乙個全域性變數或者靜態變數在源**檔案中沒有被賦予初始值,那麼在程式啟動後,在第1次被賦值前,其初始值為0。即這些資料本質上還是有初始值的,只不過初始值為0。但是當最終生成二進位制檔案時,這些未初始化資料區並不會像初始化資料區那樣,佔據它們對應變數的總大小的區域,而只是用乙個值來記錄其總大小。比如,乙個程式的**指令有100 kb大小,所有的初始化資料總大小為100kb,所有的未初始化資料總大小為150 kb,那麼在最終生成的二進位制檔案中,**區會有100 kb。接著100 kb大小的初始化資料區,然後接著乙個4個位元組大小的空間,其值為150×1024(指示其大小為150 kb),注意,這裡不是乙個150 kb大小的所有單元值都為0的空間。這樣可以節省二進位制檔案的大小,即節省硬碟空間。但是在程序虛擬位址空間中,對應於這一區域的未初始化資料區的大小必須是150 kb。因為在程式執行時,程式必須能夠真正訪問到這些變數中的每乙個。這也意味著,當程式啟動時,當監測到二進位制檔案中未初始化資料區的那個值為150×1024時,系統會開闢出乙個150 kb大小的區域作為程序的未初始化資料區域並且同時用0來初始化這一區域。

Linux程序的記憶體布局

這張圖很好,注意其中最上面是高位位址,雖然很多個0,但是c開頭的,不要看反了 更具體的可以看這裡 a.正文段。這是由cpu執行的機器指令部分。通常,正文段是可共享的,所以即使是經常執行的程式 如文字編輯程式 c編譯程式 shell等 在儲存器中也只需要有乙個副本,另外,正文段常常是唯讀的,以防止程式...

linux系統程序的記憶體布局

文章 記憶體管理模組是作業系統的心臟 它對應用程式和系統管理非常重要。今後的幾篇文章中,我將著眼於實際的記憶體問題,但也不避諱其中的技術內幕。由於不少概念是通用的,所以文中大部分例子取自32位x86平台的linux和windows系統。本系列第一篇文章講述應用程式的記憶體布局。在多工作業系統中的每乙...

Linux程序映象的記憶體布局

作業系統的程序記憶體分為5個區,區 資料區 bss區 堆區 棧區,更高層就是命令列引數和環境變數表,程序的核心空間與使用者空間分別對應不同的記憶體區。全域性常量 區 static const int static cons global 3 全域性靜態常量 區 int init global 2 全...