天天看點

現代作業系統:第三章 記憶體管理3.1 無存儲器的抽象3.2 一種存儲抽象:位址空間3.3 虛拟記憶體3.4 頁面置換算法3.5 分頁系統中存在的問題3.6 有關實作的問題3.7 分段

作業系統的工作是将這個存儲體系抽象成為一個有用的模型并将管理這個抽象模型

作業系統中管理分層存儲體系的部分稱為存儲管理器。它的任務是有效的管理記憶體,即記錄哪些記憶體是正在使用的,哪些記憶體是空閑的,在程序需要時為其配置設定記憶體,在程序使用完成的時候為其釋放記憶體。

3.1 無存儲器的抽象

最開始并沒有對存儲器進行抽象,直接簡單粗暴的使用實體記憶體位址,直接從0到某個上限值。每個位址可容納一定的二進制位存儲單元, 通常為8位。這個時期的組織記憶體的三種方式如下:

現代作業系統:第三章 記憶體管理3.1 無存儲器的抽象3.2 一種存儲抽象:位址空間3.3 虛拟記憶體3.4 頁面置換算法3.5 分頁系統中存在的問題3.6 有關實作的問題3.7 分段

即使沒有存儲器抽象,同時運作多個程式也是可能的。作業系統隻需要把目前記憶體中所有内容儲存到磁盤檔案中,然後把下一個程式讀入到記憶體中再運作即可。隻要在某個時間記憶體中隻有一個程式,那麼沖突就不會發生。

3.2 一種存儲抽象:位址空間

把實體位址直接暴露給程序會帶來下面幾個嚴重的問題:

  1. 如果使用者程式可以尋址記憶體的每一個位元組,它們就可以很容易的破壞作業系統,進而系統慢慢的停止運作。
  2. 使用這種模型,想要同時運作多個程式時很困難的。

3.2.1 位址空間的概念

位址空間是一個程序可以用于尋址的一套位址集合。每個程序都有一個自己的位址空間,并且這個位址空間獨立于其他程序的位址空間。

為了把内部虛拟位址空間轉換為真實實體位址,就需要動态重定位, 典型的辦法就是給CPU配置兩個特殊寄存器,即基址寄存器和界限寄存器。 程序加載到記憶體後,基址寄存器用來記錄程序實體記憶體的開始位置, 界限寄存器用來儲存程式的長度(也可了解為記錄程序實體記憶體的結束位置)。

如果計算機的實體記憶體足夠大,可以儲存所有的程序,那麼之前提到的方案或多或少都是可行的,但是實際上,所有程序所需要的RAM數量總和通常遠遠超過存儲器能夠支援的範圍。

這裡有兩種方法可以處理記憶體超載的調用方法:

  1. 交換技術:即把一個程序完整的調入記憶體,使該程序運作一段時間,然後把它存回到磁盤中。
  2. 虛拟記憶體技術:該政策使程式能有一部分被調用到記憶體的情況下運作。
現代作業系統:第三章 記憶體管理3.1 無存儲器的抽象3.2 一種存儲抽象:位址空間3.3 虛拟記憶體3.4 頁面置換算法3.5 分頁系統中存在的問題3.6 有關實作的問題3.7 分段

記憶體緊縮:如上圖, 運作時間長了,程序間的記憶體就可能有小塊未使用的空閑區,把小塊合成一大塊連續記憶體,就叫記憶體緊縮。但是會耗費大量CPU時間。

由于程式在運作的過程中,大部分程序的占用記憶體會在運作時不斷增長的。一種可用的方法就是:當還如或者移動記憶體的時候為他配置設定一些額外的記憶體

現代作業系統:第三章 記憶體管理3.1 無存儲器的抽象3.2 一種存儲抽象:位址空間3.3 虛拟記憶體3.4 頁面置換算法3.5 分頁系統中存在的問題3.6 有關實作的問題3.7 分段

供變量動态配置設定和釋放作為堆使用的一個資料段。存放普通局部變量和傳回位址的一個堆棧段。

3.2.3 空閑記憶體配置設定

在動态記憶體配置設定的時候,作業系統必須對其進行管理。作業系統一般有兩種方法跟蹤記憶體使用情況:位圖和空閑區連結清單。

1. 使用位圖的存儲管理

使用位圖時,記憶體被劃分為幾個或幾千個位元組的單元,即位圖中的一位,0表示空閑,1表示占用。如下:

現代作業系統:第三章 記憶體管理3.1 無存儲器的抽象3.2 一種存儲抽象:位址空間3.3 虛拟記憶體3.4 頁面置換算法3.5 分頁系統中存在的問題3.6 有關實作的問題3.7 分段

其中陰影區表示空閑記憶體,圖b 是一張位圖。圖a 一共有A/B/C/D/E 五個程序在運作。每個單元的大小很重要,單元越小,則位圖越大, 單元越大,則位圖越小。

2.使用連結清單的存儲管理

上圖c 則是用連結清單對記憶體進行管理,記憶體被劃為很多記憶體段(每一段不不一定相等),連接配接起來就是一張連結清單,一共都四個域:1.訓示标志(P表示空閑,H表示程序占用), 2、起始位址; 3.長度;4、指向下一個節點的指針。如下圖:

現代作業系統:第三章 記憶體管理3.1 無存儲器的抽象3.2 一種存儲抽象:位址空間3.3 虛拟記憶體3.4 頁面置換算法3.5 分頁系統中存在的問題3.6 有關實作的問題3.7 分段

剛開始時 A,X,B三個程序在運作,記憶體被劃為為三段,如果X終止了,則記憶體還是三段,隻是X原本占用的這一段就變為了空閑區(如圖a)。如果程序X,B都終止了,則記憶體變為了兩段(如圖b),如果A,X,B全部終止,則程序就變為了一段,如圖d.相對應的,在連結清單中的三個記憶體節點就變成了一個新的節點,老的三個節點被删除掉。

當按照位址順序在連結清單中存放程序和空閑區時,有幾種算法可以為建立程序來配置設定記憶體:

  1. 首次适配算法。
  2. 下次适配算法。
  3. 最佳适配算法。
  4. 最差适配算法。
  5. 快速适配算法。

3.3 虛拟記憶體

為了解決程式大于記憶體本身的問題,提出了這麼一種解決辦法:把程式分割成很多片段,然後程式執行時,先執行第一塊,然後執行第二塊,這樣,運作時,就隻需要把程式的部分加載到記憶體即可,這個由作業系統動态的在記憶體和磁盤上換入換出,這個方法就就演變出了虛拟記憶體。

虛拟記憶體的基本思想:每個程式有自己的位址空間,把這個空間分割為多塊,每一塊稱為一頁或頁面(page),每一頁都有連續的位址範圍。這些頁被映射到實體記憶體,但并不是所有的頁都必須再記憶體中才能運作程式。當程式引用到實體記憶體的位址空間時,由硬體立刻執行必要的映射。當程式引用到一部分不在實體記憶體的位址空間時,由作業系統負責将缺失的部分裝入實體記憶體并重新執行失敗的指令。

3.3.1 分頁

程式自己的位址稱為虛拟位址,它們構成了虛拟位址空間,虛拟位址通過記憶體管理單元(Memory Management Unit, MMU) 映射到實體記憶體位址上,進而被執行。示例圖如下:

現代作業系統:第三章 記憶體管理3.1 無存儲器的抽象3.2 一種存儲抽象:位址空間3.3 虛拟記憶體3.4 頁面置換算法3.5 分頁系統中存在的問題3.6 有關實作的問題3.7 分段

虛拟位址按照固定大小劃分為若幹個頁面, 在實體記憶體中對應的單元稱為頁框(page frame),它們大小通常是一樣的。可以了解為每個頁框可以容納一個頁面。 如上圖3-9, 虛拟頁面16個,但是實際實體位址隻有8個頁框,如果程式要通路一個沒有映射到實體頁框的頁面,就會産生缺頁中斷或稱為缺頁錯誤,

在實際硬體中,用一個“在/不在” 位(present/absent bit)來記錄頁面在記憶體中的情況,如0表示不再位, 1表示在位。

MMU當注意到該頁面沒有被映射(在圖中用叉号表示),于是CPU陷入到作業系統當中,這個陷阱稱為缺頁中斷。作業系統就會把選擇其中一個使用較少的頁框,那上面的内容清除,随後把需要通路的頁面讀到剛才回收的頁框中,修改映射關系,然後重新啟動引起陷阱的指令。

現代作業系統:第三章 記憶體管理3.1 無存儲器的抽象3.2 一種存儲抽象:位址空間3.3 虛拟記憶體3.4 頁面置換算法3.5 分頁系統中存在的問題3.6 有關實作的問題3.7 分段

在有16個虛拟頁面的情況下, 頁表由16個虛拟頁面組成,假如現在要把一個頁面加載進實體記憶體, 高四位代表在頁表的位置, 0010換成10進制就是2, 編号2的這個頁面時在位的,并且高三位的實體位址就是110,再加上低12位,就組成了一個真實的實體位址 輸出。 這就完成了16位虛拟位址到15位實體位址的轉換。

3.3.2 頁表

虛拟位址到實體位址的映射可以概括如下:虛拟位址被分為虛拟頁号(高位部分)和偏移量(低位部分)。

虛拟位址到實體位址的具體流程:虛拟頁号也可以作為頁表的索引,以找到該虛拟頁面對應的頁表項。由頁表項可以找到頁框号。然後把頁框号拼接到偏移量的高位端,以替換掉虛拟頁号,形成送往記憶體的實體位址。

頁表的目的是把虛拟頁面映射為頁框。從數學的角度上将,頁表是一個函數,它的參數是虛拟頁号,結果是實體頁框号,通過這個函數可以把虛拟位址中的虛拟頁面域替換成頁框域,進而形成實體位址。

頁表項的結構

頁框号、在不/在 位, 保護位,修改位,通路位,高速緩存禁止位。

  • 保護位:指一個頁允許什麼類型的通路, 讀、寫、可讀寫。R W X
  • 修改位:是否有修改過,修改過,則則需要先寫入磁盤儲存才能丢棄,如果沒修改過,更換其他頁面時,就可以直接丢棄了。
  • 通路位:是否正在通路、包裹讀、寫。
  • 高速緩存禁止位:禁止告訴緩存。
現代作業系統:第三章 記憶體管理3.1 無存儲器的抽象3.2 一種存儲抽象:位址空間3.3 虛拟記憶體3.4 頁面置換算法3.5 分頁系統中存在的問題3.6 有關實作的問題3.7 分段

虛拟記憶體的本質上是用來建立一個新的抽象概念----位址空間:這個概念是對于實體記憶體的抽象,類似于程序是對實體處理器(CPU)的抽象。虛拟記憶體的實作,是将虛拟位址空間分解成頁,并将每一頁映射到實體記憶體的某個頁框或者解除映射。

在任何分頁系統中我們都需要考慮下面兩個問題:

  • 虛拟位址映射到實體位址的映射必須要非常快
  • 如果虛拟位址空間很大,頁表項也很大。

3.3.3 加速分頁過程

1. 轉換檢測緩沖區

為了解決虛拟位址映射到實體位址的映射必須要非常快的問題,計算機可以設定一個小型的硬體裝置,将虛拟位址直接映射到實體位址,而不必再通路頁表。這種裝置叫做轉換檢測緩沖區 TLB。

TLB的工作原理:将一個虛拟位址放入MMU進行轉換時,硬體首先通過将該虛拟位址頁号與TLB所有表項同時進行比對,判斷頁面是否在其中。如果發現了一個有效的比對并且要進行的操作并不違反保護位,則将頁框号直接從TLB中取出而不再通路頁表。

2. 軟體管理TLB

當發生TLB通路失效的時候,将硬體管理TLB裝置交給作業系統來管理,作業系統必須首先找到該頁面,然後從TLB中删除一個項,接着裝在一個新的項,最後執行出錯前的指令。

  • 軟失效:當一個頁面通路在記憶體中,而不再TLB中,将産生軟失效。
  • 硬失效:當一個頁面本身不在記憶體中,則将産生硬失效。

3.3.4 針對大記憶體的頁表

1.多級頁表

第一種方法就是使用多級頁表。在圖中,32為的虛拟位址被劃分為10位的PT1域和10位的PT2域和12位的Offset域。因為偏移量是12位,是以頁面大小是4KB。

現代作業系統:第三章 記憶體管理3.1 無存儲器的抽象3.2 一種存儲抽象:位址空間3.3 虛拟記憶體3.4 頁面置換算法3.5 分頁系統中存在的問題3.6 有關實作的問題3.7 分段

引入多級頁表的原因是避免把全部頁表一直儲存在記憶體中。特别是那些不需要的頁表就不應該保留。

2.倒排頁表

針對頁式排程層次不斷增長的另一種解決方案是倒排頁表。表項記錄了哪一個(程序,虛拟頁面)對定位于該頁框。

現代作業系統:第三章 記憶體管理3.1 無存儲器的抽象3.2 一種存儲抽象:位址空間3.3 虛拟記憶體3.4 頁面置換算法3.5 分頁系統中存在的問題3.6 有關實作的問題3.7 分段

3.4 頁面置換算法

當缺頁中斷發生時,作業系統必須在記憶體中選擇一個頁面将其換出記憶體,以便為即将調入頁面騰出空間.如果要換出的頁面在記憶體駐留期間已經被修改過了,就必須把它寫回到磁盤上的副本,如果該頁面沒有被修改(如果一個包含程式正文的頁面),那麼它在磁盤上的副本已經是最新的,不需要寫回。直接用調入的頁面覆寫被淘汰的頁面就可以了。

在發送缺頁中斷時,需要選擇一個頁面,将其換出記憶體,應該選擇哪一個頁面呢,有如下算法:

  • 最優頁面置換算法
  • 最近未使用頁面算法
  • 先進先出頁面置換算法
  • 第二次機會頁面置換算法
  • 時鐘頁面置換算法
  • 最近最少使用頁面置換算法
  • 工作集頁面置換算法
  • 工作集時鐘頁面置換算法

針對他們的總結如下:

現代作業系統:第三章 記憶體管理3.1 無存儲器的抽象3.2 一種存儲抽象:位址空間3.3 虛拟記憶體3.4 頁面置換算法3.5 分頁系統中存在的問題3.6 有關實作的問題3.7 分段

總結:

  1. 最優置換算法在目前頁面中置換最後要通路的頁面。不幸的是,沒有辦法來判斷哪個頁面是最後要通路的,是以實際上該算法不能使用。然而,它可以作為衡量其他算法的基準。
  2. NRU(最近未使用算法)算法根據R位和M位的狀态把頁面分成四類。從編号最小的類中随機選擇一個頁面置換,該算法容易實作,但是性能不是很好。
  3. FIFO(先進先出算法)通過維護一個頁面的連結清單來記錄他們裝入記憶體的順序。淘汰最老的頁面,但是該頁面可能仍在使用,是以FIFO算法不是一個最好的選擇。
  4. 第二次機會算法是對FIFO算法的改進,他在移出頁面前先檢查該頁面釋放正在被使用。如果該頁面正在被使用,就保留該頁面。這個改進大大提高了性能。
  5. 時鐘算法是第二次機會算法的另一種實作。它具有相同的性能特征,而且隻需要更少的執行時間。
  6. LRU(最近最少未使用算法)是一種非常優秀的算法,但是隻能通過特定的硬體實作。
  7. NFU是一種近似LRU的算法,但是它的性能不是很好
  8. 最後兩種算法都使用了工作集。工作集算法有合理的性能,但它的實作開銷過于巨大。總之最後兩種算法是老化算法和工作集時鐘算法,他們分别基于LRU和工作集,它們都具有良好的頁面排程性能。

3.5 分頁系統中存在的問題

3.5.1 局部配置設定政策和全局配置設定政策

如果頁面置換算法隻考慮目前程序所配置設定的頁面,這種算法就稱為局部頁面置換算法。如果考慮所有在記憶體中的頁面,那麼這種算法就是全局頁面置換算法。局部算法可以有效的位每個程序配置設定固定大小的記憶體片段。全局算法在可以運作的程序之間動态地配置設定頁框。

全局算法在通常情況下比局部算法做的更好,當工作集的大小随程序運作時間發生變化時這種現象更加明顯。若使用局部算法,即使有大量的空閑頁框存在,工作集的增長也會導緻颠簸。

現代作業系統:第三章 記憶體管理3.1 無存儲器的抽象3.2 一種存儲抽象:位址空間3.3 虛拟記憶體3.4 頁面置換算法3.5 分頁系統中存在的問題3.6 有關實作的問題3.7 分段

3.5.2 負載控制

即使使用最優置換算法并對程序采用理想的全局配置設定,系統也可能發生颠簸。主要原因是,一旦所有程序的組合工作集超過了記憶體的容量,就可能發生颠簸。

減少競争記憶體的程序數量是一個好方法将一部分程序交換到磁盤,并且釋放他們所占有的所有頁面。即使是使用分頁,交換也是有需要的,隻是現在的交換是用來減少對記憶體潛在的需求,而不是收回它的頁面。

3.5.3 頁面大小

頁面大小是作業系統可以選擇的一個參數。一般作業系統頁面大小為4K。

随便選擇一個程式正文段、資料段、堆棧段很可能不會恰好裝滿整個頁面,平均的情況下,最後一個頁面中有一半是空的。空餘的空間就浪費掉了,這種浪費叫做内部碎片。

為了進行必要的平衡,作業系統有時候會為系統中的不同部分使用不同的頁面大小。如,核心使用大的頁面,而使用者程序使用小的頁面。

3.5.4 配置設定的指令空間和資料空間

大多數計算機的程序隻有一個位址空間,既存放程式和正文。但是位址空間通常太小了,這就使得程式員對位址空間的使用出現困難。

現代作業系統:第三章 記憶體管理3.1 無存儲器的抽象3.2 一種存儲抽象:位址空間3.3 虛拟記憶體3.4 頁面置換算法3.5 分頁系統中存在的問題3.6 有關實作的問題3.7 分段

解決方案:為指令(程式正文)和資料設定分離的位址空間,分别是I空間和D空間。

3.5.5 共享空間

在大型多道程式設計系統中,幾個不同的使用者同時運作一個程式是可見的。是以說共享頁面效率最高,但是并不是所有的頁面都适合共享。特别的那些隻讀的頁面(諸如程式文本)可以共享,但是資料頁面是不可以共享的。

如果系統支援分離的I空間和D空間,那麼兩個或者多個程序來共享程式就變得非常簡單了,這些程序使用相同的I空間頁表和不同的D空間頁表。

寫時複制

現代作業系統:第三章 記憶體管理3.1 無存儲器的抽象3.2 一種存儲抽象:位址空間3.3 虛拟記憶體3.4 頁面置換算法3.5 分頁系統中存在的問題3.6 有關實作的問題3.7 分段

3.5.6 共享庫

如果任何一個程序對一個資料頁面進行修改,系統就會為該程序複制這個資料頁面的副本,并且這個副本是程序私有的,也就是說會執行“寫時複制”。

一個更加通用的技術就是使用使用共享庫。

3.5.7 記憶體映射檔案

共享庫實際上是一種更為通用的機制----記憶體映射檔案的一個特例。記憶體映射檔案的思想是:程序可以通過發起一個系統調用,将一個檔案映射到其虛拟位址空間的一部分。

如果兩個或者兩個以上的程序同時映射了一個檔案的時候,它們就可以通過共享記憶體進行通信。一個程序在共享記憶體上完成了寫操作,此時此刻另一個程序在映射這個檔案的虛拟位址空間上執行讀操作時,它就可以看到一個程序寫操作的結果。

3.5.8 清除政策

很多分頁系統都有一個分頁守護程序的背景程序,它在大多數時候都是睡眠的,但定期被喚醒以檢查記憶體的狀态。如果空閑頁框過少,分頁守護程序通過預定的頁面置換算法選擇頁面換出記憶體。如果這些頁面裝入記憶體後被修改過,則将他們寫回到磁盤上去。

3.5.9 虛拟記憶體接口

程式員可以對記憶體映射進行控制,程式可以通過對記憶體映射進行控制來實作兩個或則多個程序共享同一部分的記憶體進行高效的消息傳遞。

3.6 有關實作的問題

3.6.1 與分頁有關的工作

作業系統在下面這四段時間内做有關分頁的工作:程序建立時,程序執行時,缺頁中斷和程序終止時。

3.6.2 缺頁中斷處理

3.6.3 指令備份

當程式不在記憶體中的頁面的時候,引起缺頁中斷的指令會半途停止并引發作業系統地陷阱。在作業系統取出所需要的頁面後,它需要重新啟動引起陷阱的指令。但這并不是一件很容易實作的事情。

CPU的設計者提出了一種解決方法,就是通過使用一個隐藏内部的寄存器。在每條指令執行之前,把程式計數器的内容複制到該寄存器中。

3.6.5 後備存儲

在磁盤上配置設定頁面空間的最簡單的算法就是設定特殊的交換分區。

最簡單的情況下,當第一個程序啟動的時候,留出于這個程序一樣大的交換區塊,剩餘的為總空間減去這個交換分區。當新程序啟動後,它們同樣被配置設定與其核心映射相同大小的交換分區。程序結束後,會釋放其磁盤的上的交換分區。

與每個程序所對應的是其交換分區的磁盤位址,即程序映像所儲存的地方。這一個資訊是記錄在程序表裡面的。

現代作業系統:第三章 記憶體管理3.1 無存儲器的抽象3.2 一種存儲抽象:位址空間3.3 虛拟記憶體3.4 頁面置換算法3.5 分頁系統中存在的問題3.6 有關實作的問題3.7 分段

3.6.6 政策和機制的配置設定

一個如何分離政策和機制的簡單列子如圖示。其中存管理系統可以分成如下三個部分:

  1. 一個底層MMU處理程式
  2. 一個作為核心一部分的缺頁中斷程式
  3. 一個運作在使用者空間中的外部頁面排程程式。
現代作業系統:第三章 記憶體管理3.1 無存儲器的抽象3.2 一種存儲抽象:位址空間3.3 虛拟記憶體3.4 頁面置換算法3.5 分頁系統中存在的問題3.6 有關實作的問題3.7 分段

3.7 分段

一個編譯器在編譯過程中會建立許多表,其中可能包括:

  1. 被儲存起來供列印清單使用的源程式正文。
  2. 符号表,包含變量的名字和屬性。
  3. 包含所有用到的整形變量和浮點變量的表。
  4. 文法分析樹。
  5. 編譯器内部過程調用的堆棧。

一個直覺并且通用的方法是在機器上提供多個互相獨立的稱為段的位址空間。每個段由一個從0 到最大的線性位址序列構成。各個段的長度可以是0到某個允許的最大值之間的任何一個值。不同的段的長度可以不同,并且通常情況下都不相同。段的長度在運作期間可以動态改變。

現代作業系統:第三章 記憶體管理3.1 無存儲器的抽象3.2 一種存儲抽象:位址空間3.3 虛拟記憶體3.4 頁面置換算法3.5 分頁系統中存在的問題3.6 有關實作的問題3.7 分段

接下來我們對分段和分頁進行了比較:

現代作業系統:第三章 記憶體管理3.1 無存儲器的抽象3.2 一種存儲抽象:位址空間3.3 虛拟記憶體3.4 頁面置換算法3.5 分頁系統中存在的問題3.6 有關實作的問題3.7 分段

繼續閱讀