1. 程式人生 > >程序地址空間與虛擬儲存空間區別

程序地址空間與虛擬儲存空間區別

在進入正題前先來談談作業系統記憶體管理機制的發展歷程,瞭解這些有利於我們更好的理解目前作業系統的記憶體管理機制。

一 早期的記憶體分配機制

在 早期的計算機中,要執行一個程式,會把這些程式全都裝入記憶體,程式都是直接執行在記憶體上的,也就是說程式中訪問的記憶體地址都是實際的實體記憶體地址。當計算 機同時執行多個程式時,必須保證這些程式用到的記憶體總量要小於計算機實際實體記憶體的大小。那當程式同時執行多個程式時,作業系統是如何為這些程式分配記憶體 的呢?下面通過例項來說明當時的記憶體分配方法:

某臺計算機總的記憶體大小是 128M ,現在同時執行兩個程式 A 和 B , A 需佔用記憶體 10M , B 需佔用記憶體 110 。計算機在給程式分配記憶體時會採取這樣的方法:先將記憶體中的前 10M 分配給程式 A ,接著再從記憶體中剩餘的 118M 中劃分出 110M 分配給程式 B 。這種分配方法可以保證程式 A 和程式 B 都能執行,但是這種簡單的記憶體分配策略問題很多。

 

圖一 早期的記憶體分配方法

問題 1 :程序地址空間不隔離。由於程式都是直接訪問實體記憶體,所以惡意程式可以隨意修改別的程序的記憶體資料,以達到破壞的目的。有些非惡意的,但是有 bug的程式也可能不小心修改了其它程式的記憶體資料,就會導致其它程式的執行出現異常。這種情況對使用者來說是無法容忍的,因為使用者希望使用計算機的時候,其中一個任務失敗了,至少不能影響其它的任務。

問題 2 :記憶體使用效率低。在 A 和 B 都執行的情況下,如果使用者又運行了程式 C,而程式 C 需要 20M 大小的記憶體才能執行,而此時系統只剩下 8M 的空間可供使用,所以此時系統必須在已執行的程式中選擇一個將該程式的資料暫時拷貝到硬碟上,釋放出部分空間來供程式 C 使用,然後再將程式 C 的資料全部裝入記憶體中執行。可以想象得到,在這個過程中,有大量的資料在裝入裝出,導致效率十分低下。

問題 3 :程式執行的地址不確定。當記憶體中的剩餘空間可以滿足程式 C 的要求後,作業系統會在剩餘空間中隨機分配一段連續的 20M 大小的空間給程式 C 使用,因為是隨機分配的,所以程式執行的地址是不確定的。

二 分段

為 瞭解決上述問題,人們想到了一種變通的方法,就是增加一箇中間層,利用一種間接的地址訪問方法訪問實體記憶體。按照這種方法,程式中訪問的記憶體地址不再是實 際的實體記憶體地址,而是一個虛擬地址,然後由作業系統將這個虛擬地址對映到適當的實體記憶體地址上。這樣,只要作業系統處理好虛擬地址到實體記憶體地址的映 射,就可以保證不同的程式最終訪問的記憶體地址位於不同的區域,彼此沒有重疊,就可以達到記憶體地址空間隔離的效果。

當建立一個程序時,作業系統會為該程序分配一個 4GB 大小的虛擬 程序地址空間。之所以是 4GB ,是因為在 32 位的作業系統中,一個指標長度是 4 位元組,而 4 位元組指標的定址能力是從 0x00000000~0xFFFFFFFF ,最大值 0xFFFFFFFF 表示的即為 4GB 大小的容量。與虛擬地址空間相對的,還有一個實體地址空間,這個地址空間對應的是真實的實體記憶體。如果你的計算機上安裝了 512M 大小的記憶體,那麼這個實體地址空間表示的範圍是 0x00000000~0x1FFFFFFF 。當作業系統做虛擬地址到實體地址對映時,只能對映到這一範圍,作業系統也只會對映到這一範圍。當程序建立時,每個程序都會有一個自己的 4GB 虛擬地址空間。要注意的是這個 4GB 的地址空間是“虛擬”的,並不是真實存在的,而且每個程序只能訪問自己虛擬地址空間中的資料,無法訪問別的程序中的資料,通過這種方法實現了程序間的地址隔離。那是不是這 4GB 的虛擬地址空間應用程式可以隨意使用呢?很遺憾,在 Windows 系統下,這個虛擬地址空間被分成了 4 部分: NULL 指標區、使用者區、 64KB 禁入區、核心區。應用程式能使用的只是使用者區而已,大約 2GB 左右 ( 最大可以調整到 3GB) 。核心區為 2GB ,核心區儲存的是系統執行緒排程、記憶體管理、裝置驅動等資料,這部分資料供所有的程序共享,但應用程式是不能直接訪問的。

      人 們之所以要建立一個虛擬地址空間,目的是為了解決程序地址空間隔離的問題。但程式要想執行,必須執行在真實的記憶體上,所以,必須在虛擬地址與實體地址間建 立一種對映關係。這樣,通過對映機制,當程式訪問虛擬地址空間上的某個地址值時,就相當於訪問了實體地址空間中的另一個值。人們想到了一種分段(Sagmentation) 的方法,它的思想是在虛擬地址空間和實體地址空間之間做一一對映。比如說虛擬地址空間中某個 10M 大小的空間對映到實體地址空間中某個 10M 大小的空間。這種思想理解起來並不難,作業系統保證不同程序的地址空間被對映到實體地址空間中不同的區域上,這樣每個程序最終訪問到的

實體地址空間都是彼此分開的。通過這種方式,就實現了程序間的地址隔離。還是以例項說明,假設有兩個程序 A 和 B ,程序 A 所需記憶體大小為 10M ,其虛擬地址空間分佈在 0x00000000 到 0x00A00000 ,程序 B 所需記憶體為 100M ,其虛擬地址空間分佈為 0x00000000 到 0x06400000 。那麼按照分段的對映方法,程序 A 在實體記憶體上對映區域為 0x00100000 到 0x00B00000 ,,程序 B 在實體記憶體上對映區域為0x00C00000 到 0x07000000 。於是程序 A 和程序 B 分別被對映到了不同的記憶體區間,彼此互不重疊,實現了地址隔離。從應用程式的角度看來,程序 A 的地址空間就是分佈在 0x00000000 到 0x00A00000 ,在做開發時,開發人員只需訪問這段區間上的地址即可。應用程式並不關心程序 A 究竟被對映到實體記憶體的那塊區域上了,所以程式的執行地址也就是相當於說是確定的了。 圖二顯示的是分段方式

的記憶體對映方法。

圖二 分段方式的記憶體對映方法

      這 種分段的對映方法雖然解決了上述中的問題一和問題三,但並沒能解決問題二,即記憶體的使用效率問題。在分段的對映方法中,每次換入換出記憶體的都是整個程式, 這樣會造成大量的磁碟訪問操作,導致效率低下。所以這種對映方法還是稍顯粗糙,粒度比較大。實際上,程式的執行有區域性性特點,在某個時間段內,程式只是訪 問程式的一小部分資料,也就是說,程式的大部分資料在一個時間段內都不會被用到。基於這種情況,人們想到了粒度更小的記憶體分割和對映方法,這種方法就是分頁 (Paging) 。  

三 分頁

分頁的基本方法是,將地址空間分成許多的頁。每頁的大小由 CPU 決定,然後由作業系統選擇頁的大小。目前 Inter 系列的 CPU 支援 4KB 或 4MB 的頁大小,而 PC上目前都選擇使用 4KB 。按這種選擇, 4GB 虛擬地址空間共可以分成 1048576 個頁, 512M 的實體記憶體可以分為 131072 個頁。顯然虛擬空間的頁數要比物理空間的頁數多得多。

在 分段的方法中,每次程式執行時總是把程式全部裝入記憶體,而分頁的方法則有所不同。分頁的思想是程式執行時用到哪頁就為哪頁分配記憶體,沒用到的頁暫時保留在 硬碟上。當用到這些頁時再在實體地址空間中為這些頁分配記憶體,然後建立虛擬地址空間中的頁和剛分配的實體記憶體頁間的對映。

下面通過介紹一個可執行檔案的裝載過程來說明分頁機制的實現方法。一個可執行檔案 (PE 檔案 ) 其實就是一些編譯連結好的資料和指令的集合,它也會被分成很多頁,在 PE 檔案執行的過程中,它往記憶體中裝載的單位就是頁。當一個 PE 檔案被執行時,作業系統會先為該程式建立一個 4GB 的程序虛擬地址空間。前面介紹過,虛擬地址空間只是一箇中間層而已,它的功能是利用一種對映機制將虛擬地址空間對映到實體地址空間,所以,建立 4GB 虛擬地址空間其實並不是要真的建立空間,只是要建立那種對映機制所需要的資料結構而已,這種資料結構就是頁目和頁表。

當建立完虛擬地址空間所需要的資料結構後,程序開始讀取 PE 檔案的第一頁。在PE 檔案的第一頁包含了 PE 檔案頭和段表等資訊,程序根據檔案頭和段表等資訊,將 PE 檔案中所有的段一一對映到虛擬地址空間中相應的頁 (PE 檔案中的段的長度都是頁長的整數倍 ) 。這時 PE 檔案的真正指令和資料還沒有被裝入記憶體中,作業系統只是根據 PE 檔案的頭部等資訊建立了 PE 檔案和程序虛擬地址空間中頁的對映關係而已。當 CPU 要訪問程式中用到的某個虛擬地址時,當 CPU 發現該地址並沒有相相關聯的實體地址時, CPU 認為該虛擬地址所在的頁面是個空頁面, CPU 會認為這是個頁錯誤 (Page Fault) , CPU 也就知道了作業系統還未給該 PE 頁面分配記憶體,CPU 會將控制權交還給作業系統。作業系統於是為該 PE 頁面在物理空間中分配一個頁面,然後再將這個物理頁面與虛擬空間中的虛擬頁面對映起來,然後將控制權再還給程序,程序從剛才發生頁錯誤的位置重新開始執行。由於此時已為 PE 檔案的那個頁面分配了記憶體,所以就不會發生頁錯誤了。隨著程式的執行,頁錯誤會不斷地產生,作業系統也會為程序分配相應的物理頁面來滿足程序執行的需求。

分頁方法的核心思想就是當可執行檔案執行到第 x 頁時,就為第 x 頁分配一個記憶體頁 y ,然後再將這個記憶體頁新增到程序虛擬地址空間的對映表中 , 這個對映表就相當於一個 y=f(x) 函式。應用程式通過這個對映表就可以訪問到 x 頁關聯的 y 頁了。

總結:

32 位的CPU 的定址空間是4G , 所以虛擬記憶體的最大值為4G , 而windows作業系統把這4G 分成2 部分, 即2G 的使用者空間和2G 的系統空間, 系統空間是各個程序所共享的, 他存放的是作業系統及一些核心物件等, 而使用者空間是分配給各個程序使用的, 使用者空間包括用: 程式程式碼和資料, 堆, 共享庫, 棧。

相關推薦

程序地址空間虛擬儲存空間區別

在進入正題前先來談談作業系統記憶體管理機制的發展歷程,瞭解這些有利於我們更好的理解目前作業系統的記憶體管理機制。 一 早期的記憶體分配機制 在 早期的計算機中,要執行一個程式,會把這些程式全都裝入記憶體,程式都是直接執行在記憶體上的,也就是說程式中訪問的記憶體地址都是實際的

Linux系統程式設計——淺談程序地址空間虛擬儲存空間

早期的記憶體分配機制 在早期的計算機中,要執行一個程式,會把這些程式全都裝入記憶體,程式都是直接執行在記憶體上的,也就是說程式中訪問的記憶體地址都是實際的實體記憶體地址。當計算機同時執行多個程式時,必須保證這些程式用到的記憶體總量要小於計算機實際實體記憶體的大小。 那當程式同時執行

淺談程序地址空間虛擬儲存空間

早期的記憶體分配機制 在早期的計算機中,要執行一個程式,會把這些程式全都裝入記憶體,程式都是直接執行在記憶體上的,也就是說程式中訪問的記憶體地址都是實際的實體記憶體地址。當計算機同時執行多個程式時,必

程序地址空間虛擬儲存空間的理解

在進入正題前先來談談作業系統記憶體管理機制的發展歷程,瞭解這些有利於我們更好的理解目前作業系統的記憶體管理機制。 一 早期的記憶體分配機制 在 早期的計算機中,要執行一個程式,會把這些程式全都裝入記憶體,程式都是直接執行在記憶體上的,也就是說程式中訪問的記憶體地址都是實際的

程序地址空間虛擬儲存空間的理解(轉載!寫的真好)

早期的記憶體分配機制在早期的計算機中,要執行一個程式,會把這些程式全都裝入記憶體,程式都是直接執行在記憶體上的,也就是說程式中訪問的記憶體地址都是實際的實體記憶體地址。當計算機同時執行多個程式時,必須保證這些程式用到的記憶體總量要小於計算機實際實體記憶體的大小。那當程式同時執

記憶體管理分析之一:Linux程序空間虛擬地址的好處

使用虛擬地址的好處現代作業系統使用了虛擬地址的方式管理各個程序對記憶體的使用,這使得應用層程式設計方便、安全,主要體現在如下方面:1,  讓每個程序擁有了相同的、獨立記憶體空間,相互之間不會干擾2,  讀寫記憶體更安全。由於系統和MMU的限制,使得程序無法操作到其他程序的資料

為什麼20位地址匯流排決定了儲存空間1MB

為什麼20位地址匯流排決定了儲存空間是: 而不是 先聽我將一個故事,請完全帶入設定: 我們家是養豬場,我的養豬場一共只有8個房間,每個房間規格是固定的的,只能養八隻豬 現在我要給養豬場的8個房間編號,我有一本像這樣的本子: (類似籃球比賽那種計分的本

RGB顏色空間Lab顏色空間區別聯絡(附轉換程式碼)

RGB顏色空間 RGB顏色是紅色(Red)、綠色(Green)和藍色(Blue)三基色的字母縮寫。RGB色彩模式是通過三種基本顏色的不同程度的迭加來產生各種各樣的不同顏色。這個標準能夠涵蓋人類視力所能

共享表空間獨立表空間、frm,MYD,MYI.idb,par文件說明

適合 數據 sla back 磁盤空間 ble .cn per 會有 一、共享表空間與獨立表空間MySQL5.5默認是共享表空間 ,5.6中,默認是獨立表空間。共享表空間:ibdata1是InnoDB的共享表空間,默認配置是把全部表空間存放到ibdata1中,因此而造成ib

用戶空間內核空間,進程上下文中斷上下文[總結]【轉】

存儲器 com ont article 模式 tab 用戶代碼 ssi 而在 轉自:http://blog.csdn.net/lizuobin2/article/details/51791863 本文轉載自:http://www.cnblogs.com/Anker/p/3

C#中抽象方法虛擬方法的區別

的人 -a 對象 abstract 數據 style html tools mar 學過C#的人應該都知道抽象方法與虛擬方法,而很多初學者對二者之間的區別並不是很了解。今天本文就來分析一下二者之間的區別。並附上實例加以說明。具體分析如下: 一、主要區別: 對於抽象方

程序的編譯解釋之間的區別

性能 clas ron 很快 負責 插入 個人 翻譯 運行速度 個人覺得:取決於你怎麽解讀這個問題。 傳統意義對比: 傳統意義上的所謂編譯與解釋,區別在於代碼是在什麽時候被翻譯成目標CPU的指令。——雖然這種解釋從科學上說不通,但這卻是一直以

向量空間線性子空間

向量空間是線性代數研究的基本物件,它是一個集合。在該集合內,可以做向量的加法(兩個向量相加仍然在該集合中),向量與標量的乘法,並且改加法與乘法還滿足八個公理。具體可參見維基百科:https://en.wikipedia.org/wiki/Vector_space 注:齊次線性方程組的

android獲取手機內部儲存空間和外部儲存空間

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

儲存儲存區別

寫入:行儲存的寫入是一次完成,資料的完整性因此可以確定。列儲存需要把一行記錄拆分成單列儲存,寫入次數明顯比行儲存多。行儲存在寫入上佔有很大的優勢資料修改:行儲存是在指定位置寫入一次,列儲存是將磁碟定位到多個列上分別寫入。行儲存在資料修改也是佔優的資料讀取:行儲存通常將一行資料

內部儲存外部儲存區別

內部儲存: 內部儲存不是記憶體,而是一個位於系統中很特殊的一個位置。放入內部儲存中的資料一般都只能被你的應用訪問到,且一個應用所建立的所有檔案都在應用包名相同的目錄下,即/data/data/pack

ios 如何獲取手機可用空間和總的儲存空間的大小

#include <sys/param.h> #include <sys/mount.h> - (void)getDivceSize{ //可用大小 struct statfs buf; long long freespac

spring的xml中p名稱空間C名稱空間簡化屬性賦值

p名稱空間與C名稱空間簡化屬性賦值 Spring給我們提供的一種比較簡便的方式來為我們的屬性賦值 P名稱空間用於簡化set方法的屬性賦值 C名稱空間用於簡化構造器的屬性賦值 第一步:加上我們的P名稱空間與C名稱空間 <?xml version="1.0" encodi

docker虛擬機的區別

linu 在操作 虛擬 dock 不同的 區別 viso eight 鏡像 Docker 是一個開源的應用容器引擎,讓開發者可以打包他們的應用以及依賴包到一個可移植的容器中,然後發布到任何流行的 Linux 機器上,也可以實現虛擬化。容器是完全使用沙箱機制,相互之間不會有任

Linux用戶空間內核空間(理解高端內存)

x86架構 c11 see 主機名 gen 偏移 nmap hat eth Linux 操作系統和驅動程序運行在內核空間,應用程序運行在用戶空間,兩者不能簡單地使用指針傳遞數據,因為Linux使用的虛擬內存機制,用戶空間的數據可能被換出,當內核空間使用用戶空間指針時,對應的