操作系統:基礎內存管理

帕金森定律:不管存儲器有多大,程序都可以把它填滿。

分層存儲體系(memory hierarchy):KB 級寄存器,MB 級快速、昂貴且易失的高速緩存(cache),GB 級速度與價格適中但同樣易失的內存,以及 TB 級低速、廉價、非易失的磁盤存儲,還有 DVD 和 USB 等可移動存儲裝置。

操作系統的工作是將這個存儲體系抽象爲一個有用的模型並管理這個抽象模型。

操作系統中管理分層存儲體系的部分稱爲存儲管理器(memory manager)。它的任務是有效地管理內存,即記錄哪些內存是正在使用的,哪些內存是空閒的;在進程需要時爲其分配內存,在進程使用完後釋放內存。


無存儲器抽象

在沒有存儲器抽象的系統中實現並行的一種方法是使用多線程來編程。由於在引入線程時就假設一個進程中的所有線程對同一內存映像都可見,那麼實現並行也就不是問題,

在不使用存儲器抽象的情況下運行多個程序

操作系統只需要把當前內存中所有內容保存到磁盤文件中,然後把下一個程序讀入到內存中再運行即可。只要在某一個時間內存中只有一個程序,那麼就不會發生衝突。

在特殊硬件的幫助下(防止用戶進程之間相互干擾),即使沒有交換功能,併發地運行多個程序也是可能的。但這樣會有重定位問題

  • 保護:(IBM 360)給內存塊標記上一個保護鍵,並且比較執行進程的鍵和其訪問的每個內存字的保護鍵。
  • 靜態重定位:當一個程序被裝載到地址16384時,常數16384被加到每一個程序地址上。裝載器還需要一定的方法來辨別地址和常數。

基礎內存管理:連續分配

一種存儲器抽象:地址空間

把物理地址暴露給進程會帶來兩個嚴重問題:

  1. 如果用戶程序可以尋址內存的每個字節,那麼它們就可以很容易地破壞操作系統。即使在只有一個用戶進程運行的情況下,這個問題也是存在的。
  2. 在系統中沒有對物理內存的抽象的情況下,很難實現同時運行多個程序。

地址空間的概念

要使多個應用程序同時處於內存中並且不相互影響,需要解決兩個問題:保護的和重定位

比無存儲器抽象時的保護和靜態重定位更好的辦法是創造一個新的存儲器抽象:地址空間

就像進程的概念創造了一類抽象的 CPU 以運行程序一樣,地址空間爲程序創造了一種抽象的內存,是一個進程可用於尋址內存的一套地址集合。每個進程都有一個自己的地址空間,並且這個地址空間獨立於其他進程的地址空間。

  • 動態重定位
    • 基址寄存器
    • 界限寄存器
    • 當使用基址寄存器和界限寄存器時,程序裝載到內存中連續的空閒位置且裝載期間無須重定位,當一個程序運行時,程序的起始物理地址裝載到基址寄存器中,程序的長度裝載到界限寄存器中。
    • 使用基址寄存器和界限寄存器重定位的缺點是:每次訪問內存都需要進行加法和比較運算。

交換技術

有兩種處理內存超載的通用方法。

  • 交換技術:即把一個進程完整調入內存,使該進程運行一段時間,然後把它存回磁盤。
  • 虛擬內存:能使程序在只有一部分被調入內存的情況下運行。

交換在內存中產生了多個空閒區(hole,也稱爲空洞),通過把所有的進程儘可能向下移動,有可能將這些小的空閒區合成一大塊。該技術稱爲內存緊縮(memory compaction)。

如果進程在運行時內存需要增長,爲了減少因內存不夠而引起的進程交換和移動所產生的開銷,當換入或移動進程時可以爲它分配一些額外的內存。

  • 爲可能增長的數據段預留空間;
  • 爲可能增長的數據段和堆棧段預留空間。

空閒內存管理

  • 使用位圖的存儲管理
    • 分配單元的大小是一個重要的設計因素。內存的大小和分配單元的大小決定了位圖的大小。
    • 主要問題:查找位圖中指定長度的連續0串是耗時的操作。(爲了把一個佔 k 個分配單元的進程調入內存)
  • 使用鏈表的存儲管理
    • 維護一個記錄已分配內存段和空閒內存段的鏈表。其中鏈表的一個結點或者包含一個進程,或者是兩個進程間的一塊空閒區。
    • 鏈表中的每一個結點都包含以下域:空閒區(H)或進程(P)的指示標識、起始地址、長度和指向下一結點的指針。
    • 當按照地址順序在鏈表中存放進程和空閒區時,有以下幾種算法可以用來爲創建的進程,或從磁盤換入的已存在的進程分配內存(假設存儲管理器知道要爲進程分配多少內存):
      • 首次適配
      • 下次適配:每次從上次結束的地方開始搜索。
      • 最佳適配:比首次適配算法慢,而且比首次適配和下次適配算法浪費更多的內存,因爲它會產生大量無用的小空閒區。
      • 最差適配
      • 快速適配:爲那些常用大小的空閒區維護單獨的鏈表。
        • 優點:尋找一個指定大小的空閒區是十分快速的。
        • 缺點:在一個進程終止或被換出時,尋找它的相鄰塊並查看是否可以合併的過程非常費時。
  • 夥伴式的內存管理
    • 拆分和合並涉及到較多的鏈表和位圖操作。
    • Buddy算法的分配原理:
      • 假如系統需要4(2*2)個頁面大小的內存塊,該算法就到free_area[2]中查找,如果鏈表中有空閒塊,就直接從中摘下並分配出去。如果沒有,算法將順着數組向上查找free_area[3],如果free_area[3]中有空閒塊,則將其從鏈表中摘下,分成等大小的兩部分,前四個頁面作爲一個塊插入free_area[2],後4個頁面分配出去,free_area[3]中也沒有,就再向上查找,如果free_area[4]中有,就將這16(2*2*2*2)個頁面等分成兩份,前一半掛如free_area[3]的鏈表頭部,後一半的8個頁等分成兩等分,前一半掛free_area[2]的鏈表中,後一半分配出去。假如free_area[4]也沒有,則重複上面的過程,直到到達free_area數組的最後,如果還沒有則放棄分配。
    • Buddy算法的釋放原理:
      • 內存的釋放是分配的逆過程,也可以看作是夥伴的合併過程。當釋放一個塊時,先在其對應的鏈表中考查是否有夥伴存在,如果沒有夥伴塊,就直接把要釋放的塊掛入鏈表頭;如果有,則從鏈表中摘下夥伴,合併成一個大塊,然後繼續考察合併後的塊在更大一級鏈表中是否有夥伴存在,直到不能合併或者已經合併到了最大的塊。

基礎內存管理:離散分配

  • 分段
  • 分頁
    • 多級頁表
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章