記憶體管理筆記(分頁,分段,邏輯地址,物理地址)【轉】

來源:互聯網
上載者:User

標籤:

本文轉載自:http://www.cnblogs.com/felixfang/p/3420462.html

1. 物理地址和邏輯地址

物理地址:載入到記憶體位址寄存器中的地址,記憶體單元的真正地址。在前端匯流排上傳輸的記憶體位址都是實體記憶體地址,編號從0開始一直到可用實體記憶體的最高端。這些數字被北橋(Nortbridge chip)映射到實際的記憶體條上。物理地址是明確的、最終用在匯流排上的編號,不必轉換,不必分頁,也沒有特權級檢查(no translation, no paging, no privilege checks)。

邏輯地址:CPU所產生的地址。邏輯地址是內部和編程使用的、並不唯一。例如,你在進行C語言指標編程中,可以讀取指標變數本身值(&操作),實際上這個值就是邏輯地址,它是相對於你當前進程資料區段的地址(位移地址),不和絕對物理地址相干。

為什麼會有這兩種地址?

個人覺的原因在於邏輯地址分配更加靈活,可以允許不唯一,看起來也較為直觀,例如,一段代碼中分配數組,邏輯地址上是連續的,然而在物理地址上,這個數組所佔用的頁可能分散開來,物理地址上就是不連續的,這樣對程式的可理解性上有影響。另外,有了邏輯地址這個概念,才能使用虛擬記憶體技術。

2. Paging,分頁記憶體管理方案

(1) 分頁的最大作用就在於:使得進程的物理地址空間可以是非連續的。

實體記憶體被劃分為一小塊一小塊,每塊被稱為幀(Frame)。分配記憶體時,幀是分配時的最小單位,最少也要給一幀。在邏輯記憶體中,與幀對應的概念就是頁(Page)。

邏輯地址的表示方式是:前部分是頁碼後部分是頁位移。

例如,已知邏輯空間地址為2^m個位元組(也就是說邏輯地址的長度是m位),已知頁大小是2^n位元組。那麼一共可以有2^(m-n)個頁。因此頁碼部分會佔m-n位,之後的n位,用來儲存頁位移。

舉個例子, 頁大小為4B,而邏輯記憶體為32B(8頁),邏輯地址0的頁號為0,頁號0對應幀5,因此邏輯地址映射為物理地址5*4+0=20。邏輯地址3映射物理地址5*4+3=23。邏輯地址13(4*3+1,頁號為3,位移為1,因此幀號為2),映射到物理地址9。

採用分頁技術不會產生外部片段(記憶體都被劃分為幀),但可能產生內部片段(幀已經是最小單元,因此幀內部可能有空間沒有用到)。

按機率計算下來,每個進程平均可有半個幀大小的內部片段。

(2) 頁表的硬體實現

上一小節中寫到頁表是邏輯地址轉化到物理地址的關鍵所在。那麼頁表如何儲存?

每個作業系統都有自己的方法來儲存頁表。絕大多數都會為每個進程分配一個頁表。現在由於頁表都比較大,所以放在記憶體中(以往是放在一組專用寄存器裡),其指標存在進程式控制制塊(PCB)裡,當進程被發送器選中投入運行時,系統將其頁表指標從進程式控制制塊中取出並送入使用者寄存器中。隨後可以根據此首地址訪問頁表。

頁表的儲存方式是TBL(Translation look-aside buffer, 翻譯後備緩衝器)+記憶體。TBL實際上是一組硬體緩衝所關聯的快速記憶體。若沒有TBL,作業系統需要兩次記憶體訪問來完成邏輯地址到物理地址的轉換,訪問頁表算一次,在頁表中尋找算一次。TBL中儲存頁表中的一小部分條目,條目以索引值對方式儲存。

(3) 頁表的資料結構

a.

今年是2013年,現有的膝上型電腦,記憶體位址空間一般為2^32位元組以上。對於具有32位邏輯地址空間的電腦系統,如果系統的頁大小為4KB(2^12B),那麼頁表可以擁有2^(32-12)個,也就是一百多萬個條目,假設每個條目佔有4B,那每個進程都需要4MB的物理地址空間來存放頁表本身。而且,頁表本身需要分配在連續記憶體中。

為此,Hierarchical Paging(層次化分頁)被提出,實際上就是將頁號分為兩部分,第一部分作為索引,第二部分作為頁號的位移。

以一個4kb頁大小的32位系統為例。一個邏輯地址被分為20位的頁碼和12位的頁位移。因為要對頁表進行再分頁,所以該頁號可分為10位的頁碼和10位的頁位移。這樣一個邏輯地址就表示如下形式:

 

地址轉換過程如下:

 

地址由外向內轉換,因此此方法也被稱為forward-mapped page table(向前映射表)

b. Hashed Page Tables 雜湊頁表

處理超過32位地址空間的常用方法是使用hashed page table(雜湊頁表),並以虛擬頁碼作為雜湊值。雜湊頁表的每一條目都包括一個鏈表的元素,這些元素雜湊成同一位置。每個元素有三個域:虛擬頁碼,所映射的幀號,指向鏈表中下一個元素的指標。

個人看來,雜湊頁表的地址轉換方式,實際上是Chaining(連結)方式,也就是一種雜湊函數的溢出處理方式(另一種溢出處理方式叫做Open Addressing,開放定址),具體過程如下:

邏輯地址需要大於32bit的地址空間來表示,但是作業系統仍只有32bit來表示地址。此時人們便想到虛擬頁地址,虛擬位址可以在32bit表示範圍之內,然後利用雜湊函數完成邏輯地址到虛擬位址的映射,由於虛擬位址更少,雜湊函數會出現溢出,這裡使用Chaining來解決溢出。

邏輯地址中的頁號(中的p)經過雜湊函數的計算,算出虛擬位址中的頁號,根據虛擬頁號可以在雜湊表中以O(1)方式定址,用p與鏈表中的每一個元素的第一個域相比較。如果匹配,那麼相應的幀號就用來形成物理地址。如果不匹配,就對鏈表中的下一個節點進行比較,以尋找一個匹配的頁號。

c. Inverted page table 反向頁表

時間關係,這段暫時略過。

3. Segmentation,分段記憶體管理方案

採用分頁記憶體管理有一個不可避免的問題:使用者視角的記憶體和實際記憶體的分離。設想一段main函數代碼,裡麵包含Sqrt函數的調用。按照編寫者的理解,這段代碼運行時,作業系統應該分配記憶體給:符號表(編譯時間使用),棧(存放局部變數與函數參數值),Sqrt程式碼片段,主函數程式碼片段等。這樣,編寫者就可以方便地指出:"函數sqrt記憶體模組的第五條指令",來定位一個元素。而實際上,由於採用Paging的管理方式,所有的一切都只是散落在實體記憶體中的各個幀上,並不是以編寫者的理解來劃分模組。

Segmentation的記憶體管理方式可以支援這種思路。邏輯地址空間由一組段組成。每個段都有名字和長度。地址指定了段名稱和段內位移。因此使用者通過兩個量來指定地址:段名稱和位移。段是編號的,通過段號而非段名稱來引用。因此邏輯地址由有序對構成:

 <segment-number,offset>(<段號s, 段內位移d>)

段位移d因該在0和段界限之間,如果合法,那麼就與基地址相加而得到所需位元組在實體記憶體中的地址。因此段表是一組基地址和界限寄存器對。

 

例如,有5個段,編號0~4,例如段2為400B開始於位置4300,對段2第53位元組的引用映射成位置4300+53=4353。而段0位元組1222的引用則會觸發地址錯誤,因為該段的僅為1000B長(界限為1000)。

4. 合并分段和分頁的管理方案

在現有的Intel相容電腦(x86)上,採用的記憶體管理方案是分段和分頁合并的管理方案。

在這個方案中,邏輯地址,如前一節中所說,是由一個段標識符加上一個指定段內相對位址的位移量,表示為 [段標識符:段內位移量]。

這樣的邏輯地址轉換的過程是怎樣呢?如所示:

當CPU要執行一條引用了記憶體位址的指令時,轉換過程就開始了。第一步是把邏輯地址轉換成線性地址。但是,為什麼不跳過這一步,而讓軟體直接使用線性地址(或物理地址呢?)原因主要是因為:

(1) Intel的更新是漸進式而非革命式,新的處理器需要相容和保留過往的設定。具體的原因,博文Memory Translation and Segmentation (http://blog.csdn.net/drshenlei/article/details/4261909) 中講的較為清楚。

(2) 如上節所說,採用段記憶體管理,可以跟方便地進行地址保護(同一類型的地址邏輯地址在一起)。

下面講邏輯地址到線性地址的部分。

在IBM OS/2 32位版本的作業系統,和Intel 386的環境下。作業系統採用的記憶體配置方式就是分段和分頁合并的方式。

邏輯地址的實際上是一對<選擇符,位移>。

選擇符的內容如下:

從左開始,13位是索引(或者稱為段號),通過這個索引,可以定位到段描述符(segment descriptor),而段描述符是可以真正記載了有關一個段的位置和大小資訊, 以及存取控制的狀態資訊。段描述符一般由8個位元組組成。由於8B較大,而Intel為了保持向後相容,將段寄存器仍然規定為16-bit(儘管每個段寄存器事實上有一個64-bit長的不可見部分,但對於程式員來說,段寄存器就是16-bit的),那麼很明顯,我們無法通過16-bit長度的段寄存器來直接引用64-bit的段描述符。因此在邏輯地址中,只用13bit記錄其索引。而真正的段描述符,被放於數組之中。

這個記憶體中的數組就叫做GDT(Global Descriptor Table,全域描述表),Intel的設計者門提供了一個寄存器GDTR用來存放GDT的入口地址。程式員將GDT設定在記憶體中某個位置之後,可以通過LGDT指令將GDT的入口地址裝入此寄存器,從此以後,CPU就根據此寄存器中的內容作為GDT的入口來訪問GDT了。

除了GDT之外,還有LDT(Local Descriptor Table,本地描述表),但與GDT不同的是,LDT在系統中可以存在多個,每個進程可以擁有自己的LDT。LDT的記憶體位址在LDTR寄存器中。

在之前圖中的TI位,就是用來表示此索引所指向的段描述符是存於全域描述表中,還是本地描述表中。=0,表示用GDT,=1表示用LDT。

RPL位,佔2bit,是保護資訊位,還沒有仔細瞭解過這一塊,暫時先不寫。

找到,段描述符後,加上位移量,便是線性地址。轉換過程如下:

在Intel 386的環境下,線性地址轉換為物理地址的過程,和第二節分頁式記憶體管理中,層次分頁中,邏輯地址轉換為物理地址的方法類似。如。

 

Intel 80386的地址轉換全過程如:

 

記憶體管理部分是作業系統的核心功能之一,這次將理論部分整理出來,一是為了複習,二也是為了提綱挈領地為深入學習作業系統做準備。

記憶體管理筆記(分頁,分段,邏輯地址,物理地址)【轉】

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.