1. 程式人生 > >分段 分頁 虛擬記憶體空間 邏輯地址 實體地址

分段 分頁 虛擬記憶體空間 邏輯地址 實體地址

一、虛擬記憶體空間

  虛擬記憶體空間是系統的一種技術,當程式被載入記憶體時,運用虛擬記憶體空間技術讓程式誤認為自己目前獨佔電腦記憶體,能夠佔用電腦所有的記憶體,訪問所有記憶體地址。
以32位作業系統為例:
  32位系統程式的指標為32位(4位元組),2^32 = 4GB,也就是說指標可以取值的方法有2^32種,可以訪問2^32地址。這也就為什麼有種說法:32位系統支援裝最高4g記憶體。當程式載入記憶體後,系統為程式賦予4GB虛擬空間。而程式理解在虛擬空間中的地址就是邏輯地址。但是邏輯地址只是一種假象,並不是指系統真的為程式分配了4GB記憶體。如下圖,程式載入虛擬記憶體空間:
這裡寫圖片描述
  上圖中程式的.text段基址是0x08048000,0x08048000就是虛擬地址,每個被載入記憶體的程式都有可能基址是0x08048000。這是運用了虛擬記憶體空間技術,實際中是不可能存在的,如果每個程式都使用真實地址0x08048000記憶體,那兩個程式就互相干預,導致資料的混亂。
  那是不是這 4GB 的虛擬地址空間應用程式可以隨意使用呢? Windows 系統中,這個虛擬地址空間被分成了 4 部分: NULL 指標區、使用者區、64KB 禁入區、核心區等。
1、NULL指標分割槽是NULL指標的地址範圍。對該區域的讀寫將引發訪問違規。
2、使用者分割槽是應用程式能使用的,大約 2GB 左右。 使用者分割槽又進行了詳細的分割槽。

PE檔案結構對程式進行了分割槽
3、禁止訪問分割槽只有在win2000中有。這個分割槽是使用者分割槽和核心分割槽之間的一個隔離帶,目的是為了防止使用者程式違規訪問核心分割槽。
4、 核心方式分割槽對使用者的程式來說是禁止訪問的,作業系統的程式碼在此。核心物件也駐留在此。
  由上會產生一個疑問?雖然程式被分配在虛擬空間,但是程式要想執行的話最終還是要回歸到真實記憶體中來。如果程式需要記憶體大於4GB,而系統只有4GB記憶體。那程式不還是執行不了。
  實際上程式載入記憶體時並不是一次性全部載入記憶體。程式執行時存在區域性性現象,就是說程式在短時間內只會執行某一區域性程式碼。因此僅需將那些當前需要的少數頁面或段載入記憶體即可執行,但系統繼續往下執行,發現缺頁或缺段就會觸發中斷請求,由作業系統將程式請求的頁或段載入記憶體,繼續執行。

二、分段 分頁

  多個程式的執行,對記憶體的使用和銷燬會使得記憶體產生許多碎片。但需要載入一個新程式為20M,而記憶體目前存有三個碎片:5M,15M,8M。任何一個碎片都不能完整載入整個程式。那麼我們可不可以那20M程式分成5M,15M,5M分別載入這三個記憶體碎片中呢?基於此思想產生離散式記憶體分配。分為如下三種:
分頁儲存管理:
  將使用者程式的地址空間分成若干個固定大小區域,稱為頁,同時將記憶體空間分成對應大小物理塊。系統中維護一個頁表,通過頁與物理塊的對應,完成邏輯地址到實體地址(實際記憶體的地址,比如記憶體條)的對映。
這裡寫圖片描述
  當程序訪問某個邏輯地址中資料,分頁系統地址變換機構,用頁號檢索頁表,如果頁號大於或等於頁表長度,則產生地址越界中斷。否則將頁表初始地址與頁號和頁表項長度乘積相加得到頁表物理號的地址,獲取到物理塊號。再將物理塊得到的地址與頁內地址組合得到實體地址。
  如果選擇的頁面太小,雖然可以提高記憶體利用率,但是每個程序使用過多頁面,導致頁表過長。降低頁面換入換出效率。
分段儲存管理:


  將程式地址空間分成若干段,段大小不定,每段定義一組相對完整資訊,在記憶體分配時以段為單位。
這裡寫圖片描述
這裡寫圖片描述
其地址變換與分頁類似。
  分段的使用為了滿足使用者的程式設計和使用要求。使用者通常將自己的程式按邏輯分成若干段,每段從0開始編址,有名稱和長度,如:程式段text,資料段data。棧等。所以彙編中程式設計師訪問的地址由段號和段內地址決定的。常有段暫存器:
  段(segment)暫存器:
    程式碼段(code segment)暫存器CS;
    堆疊段(stack segment)暫存器SS;
    資料段(data segment)暫存器DS;
    附加段暫存器ES;
而且段的使用有利於資訊共享,分頁儲存的話一個共享的過程往往需要佔用數十個頁面;資訊保護同樣可以以邏輯單位為基礎,且經常以一個過程、函式或檔案為基本單位;同理段儲存很好解決了資料段動態增長,程式的動態連結等問題。 
段頁式儲存管理:
同時利用分頁儲存和分段儲存優勢,過程類似。
這裡寫圖片描述
這裡寫圖片描述

三、系統對邏輯地址的管理

  程式有時候需要分配一段連續記憶體,實體記憶體由於多次重複分配產生很多碎片。目前邏輯地址記憶體和實體記憶體佔用如下:
這裡寫圖片描述
  在使用GlobalAlloc等函式時,指定GMEM_MOVABLE(允許系統對邏輯地址進行管理)和GMEM_FIXED引數(允許在實體記憶體中移動記憶體塊,但是必須保證邏輯地址是不變的。),對上面邏輯記憶體使用GMEM_MOVABLE引數時形成如下連續記憶體:
這裡寫圖片描述