天天看點

深入了解程序(二)——虛拟位址空間

深入了解程序(一)——虛拟位址空間

一、為什麼要有虛拟位址空間?

​ 在談論虛拟位址空間之前,大家要知道一個常識:程式在運作之前是要全部加載到記憶體中的。

假如現在有兩個程式,一個大小為4M,一個大小為8M,而我們的記憶體大小為16M。首先我們運作4M大小的程式,将其加載到記憶體中,然後再運作8M大小的程式,同樣将其加載到記憶體中,如下圖所示:

深入了解程式(二)——虛拟位址空間

那麼這個時候我們還剩餘4M的空間,此時如果我們想要再加載一個6M大小的程式,那麼肯定就加載不了,因為記憶體不夠,但是如果這個程式的優先級很高,那麼作業系統就會把4M的程式從記憶體中拿出來,如下圖所示:

深入了解程式(二)——虛拟位址空間

這個時候記憶體剩餘空間大小為8M,如果僅僅從空間大小來看,那麼是完全可以加載6M大小的程式。而實際上,卻是無法加載的,因為程式不可分割,要麼有足夠且連續的空間将6M大小的程式一次性全部加載完畢,要麼不加載。是以我們發現這樣的記憶體管理的效率太低,并且浪費了大量的空間,是以才會有之後的虛拟位址空間。

二、什麼是虛拟位址空間

​ 所謂的虛拟位址空間,大家從它的名字就可以聽出來,這個空間實際上不存在的,也就是說,它并不像我們所說的實體空間一樣是現實存在的。大家可以這樣了解,一天同學A告訴同學B需要100平方米的地去種小麥,然後B去找地,可是并沒有找到連續的100平方米的地,但是他找到了兩塊50平方米的地,隻不過兩塊地不在一起。于是B就對A撒謊,說我找到了一塊100平方米的地,A也是心大,也不去證明,并且讓B幫忙在地上種下小麥,來年豐收,兩位同學都很開心。這就是虛拟位址空間,B并沒有找到連續的100平方米的地,于是用兩塊50平方米的去欺騙A,雖然欺騙了A,但是最終結果與預期的一樣,這就行了。

​ 現在來了解虛拟位址空間,作業系統為每一個程序都會設定屬于自己的虛拟位址空間,換句話說就是,作業系統欺騙了程序,将本來間斷的記憶體空間通過一個虛拟位址空間讓程序相信自己所加載的程式處于一個連續的空間之中。也可以了解為,作業系統将一個程序劃分為多個塊,每個塊不需要連續位于記憶體中,這些塊再通過一種映射關系映射到實際的實體位址上。程序通路的都是虛拟位址,而作業系統再通過虛拟位址來尋找實際的實體位址,這就是虛拟位址空間。

三、Linux下虛拟位址空間的布局

深入了解程式(二)——虛拟位址空間

核心空間:

核心總是駐留在記憶體中,是作業系統的一部分。核心空間為核心保留,不允許應用程式讀寫該區域的内容或直接調用核心代碼定義的函數。

棧:

由編譯器自動配置設定釋放,行為類似資料結構中的棧(先進後出),它是向下增長的,也就是說向低位址增長

局部變量、函數參數、傳回位址等

共享映射段:

裝載動态共享庫,如C标準庫函數(fread、fwrite、fopen等)和Linux系統I/O函數

堆:

堆用于存放程序運作時動态配置設定的記憶體段,可動态擴張或縮減。堆中内容是匿名的,不能按名字直接通路,隻能通過指針間接通路。它是向上增長的。

BSS:

未初始化或初值為0的全局變量和靜态局部變量

已初始化全局變量:

已初始化且初值非0的全局變量和靜态局部變量

代碼段:

可執行代碼、字元串字面值、隻讀變量

我将在下一節講述虛拟位址是如何轉換為實體位址的

繼續閱讀