天天看點

虛拟位址空間

虛拟位址空間的配置設定與系統環境有關:

下圖為linux X86環境

虛拟位址空間
虛拟位址空間

*

保留區即為受保護的位址,大小為0~4K,位于虛拟位址空間的最低部分,未賦予實體位址(不會與記憶體位址相對應,是以其不會放任何内容)。 任何對它的引用都是非法的,用于捕捉使用空指針和小整型值指針引用記憶體的異常情況。大多數作業系統中,極小**的位址通常都是不允許通路的,如NULL。** C語言将無效指針指派為0也是出于這種考慮,因為0位址上正常情況下不會存放有效的可通路資料。将指針指派為0,意味着該指針将永遠不會被使用, 進而不會出現野指針情況。 #define NULL 0 與 #define NULL (void)0 在C語言中是等效的,而在C++中 ,隻能 用#define NULL 0,後面 #define NULL (void)0的使用會出錯。
代碼段也稱正文段或文本段,通常用于存放程式執行代碼(即CPU執行的機器指令)。一般C語言執行語句都編譯成機器代碼儲存在代碼段。通常代碼段是可共享的,是以頻繁執行的程式隻需要在記憶體中擁有一份拷貝即可。代碼段通常屬于隻讀,以防止其他程式意外地修改其指令(對該段的寫操作将導緻段錯誤)。某些架構也允許代碼段為可寫,即允許修改程式。
資料段通常用于存放程式中已初始化的全局變量和靜态局部變量。資料段屬于靜态記憶體配置設定(靜态存儲區),可讀可寫。由于全局變量未初始化時,其預設值為0,是以值為0的全局變量位于.bbs段(不位于資料段)。對于未初始化的局部變量,其值是不可預測的。注意:在代碼段和資料段之間還包括其它段:隻讀資料段和符号段等。
該段用于存放未初始化的全局變量和靜态局部變量,包括值為0的全局變量。 資料段和.bbs段又稱為全局資料區,前者初始化,後者未初始化。 ELF段包括:代碼段、其它段(隻讀資料段和符号段等)、.data段(資料段)和.bbs段,都屬于可執行程式部分。
new( )和malloc( )函數配置設定的空間就屬于對空間,用于記憶體空間的配置設定,其從下往上。 堆用于存放程序運作時動态配置設定的記憶體段,可動态擴張或縮減。堆中内容是匿名的,不能按名字直接通路,隻能通過指針間接通路。當程序調用malloc(C) 和new (C++)等函數配置設定記憶體時,新配置設定的記憶體動态添加到堆上(擴張);當調用free(C)/delete(C++)等函數釋放記憶體時,被釋放的記憶體從堆中剔除(縮減) 。
此處,核心将硬碟檔案的内容直接映射到記憶體, 任何應用程式都可通過Linux的mmap()系統調用請求這種映射。記憶體映射是一種友善高效的檔案I/O方式, 因而被用于裝載動态共享庫。如C标準庫函數(fread、fwrite、fopen等)和Linux系統I/O函數,它們都是動态庫函數,其中C标準庫函數都被封裝在了/lib/libc.so庫檔案中,都是二進制檔案。這些動态庫函數都是與位置無關的代碼,即每次被加載進入記憶體映射區時的位置都是不一樣的,是以使用的是其本身的邏輯位址,經過變換成線性位址(虛拟位址),然後再映射到記憶體。而靜态庫不一樣,由于靜态庫被連結到可執行檔案中,是以其位于代碼段,每次在位址空間中的位置都是固定的。
用于存放局部變量(非靜态局部變量,C語言稱為自動變量),配置設定存儲空間時從上往下。棧和堆都是後進先出的資料結構。
該段用于存放指令行參數的内容:argc和argv。
用于存放目前的環境變量,在Linux中用env指令可以檢視其值。
1.方面編譯器和作業系統安排程式的位址;2.友善實作各個程序空間之間的隔離,互不幹擾,因為每個程序都對應自己的虛拟位址空間;3.實作虛拟存儲,從邏輯上擴大了記憶體。
代碼段(.text段)與隻讀資料段和符号段(.rodata段),都屬于隻能讀的部分,在連結的時候這兩部分會連結成為一個整體;而.data段和.bbs段屬于可讀可寫RW的部分。這四個部分都是以頁(每頁4KB)的形式存放在記憶體中。程序控制塊PCB(又叫程序描述符)放于核心空間。

轉載自:https://blog.csdn.net/qq_33883085/article/details/88430087