現代操作系統學習筆記-存儲管理

0.無存儲器抽象

  • 通常程序引用絕對物理地址
  • 在嵌入式系統和智能卡系統中,比較常見

一.地址空間

地址空間是一個進程可用於尋址內存的一套地址集合

1.通常爲每個CPU配置兩個寄存器:基址寄存器與界限寄存器

  • 基址寄存器:存儲程序的起始物理地址
  • 界限寄存器:存儲程序的長度

2.當取址時自動將基址值加到進程發出的地址值上,檢查該地址是否超過界限寄存器計算後的值

  • 每次訪問內存都要加法運算和比較,而加法運算比較耗時

3.交換技術

交換技術,把一個進程完整的調入內存,使該進程運行一段時間,然後把它存回磁盤

  • 內存緊縮,交換在內存中產生很多個空閒區,通過把所有進程儘可能向下移動,有可能將小的空閒區合併成一個大塊,但是這個操作非常耗時
  • 另一種方案爲提前預留出一些內存空間給進程,當交換時僅將實際使用的空間交換出去
  • 也可分配一大塊,上邊爲堆棧,下邊爲程序,程序上邊爲數據,中間空閒區域爲堆,供給數據和堆棧使用
    堆棧

4.空閒內存管理

1)位圖存儲管理:每個分配單元對應於位圖中的一位,0表示空閒,1表示佔用(或相反)
這裏寫圖片描述

  • 分配單元越小,位圖越大;反之位圖越小,但可能最後一塊浪費較多
  • 查找指定長度的連續0串是耗時的,因爲可能跨越字的邊界?

2)鏈表存儲管理:維護一個記錄已分配內存和空閒內存段的鏈表,其中鏈表中的一個結點或者包含一個進程,或者是兩個進程間的一個空閒區,P爲進程,H爲空閒區,X爲終點
這裏寫圖片描述

常用算法:

  • 首次適配:沿着鏈表找到一個足夠大的空閒區,佔用部分或全部,剩下的部分爲新的空閒區
  • 下次適配:與首次相似,但需記住位置,用以下次查詢,性能相對較低
  • 最佳適配:找到空閒區剛好等於或略大於所需空間的區域,性能差,碎片多
  • 最差適配:總是找到當前最大的空閒區分配,也不是最優
  • 兩個鏈表:一個存使用中的空間,另一個存空閒區,好處是可以提高上述算法效率,但是增大了複雜度,和內存釋放難度(將釋放進程從進程表中刪除,再插入到空閒表),小優化:利用單鏈表中的空閒區,第一個字是當前空閒區大小,第二個字指向下一個空閒區,第三個依舊指向下一個順序節點,如此不需要P/H位
  • 快速適配:爲常用大小的空閒區維護單獨立鏈表,如4KB 8KB 12KB 等,21KB可以放在20KB表中,也可單獨維護一個21KB

二.虛擬內存

基本思想:每個進程擁有自己的地址空間,這個空間被分割成多個塊,每一塊稱作一頁或頁面,每一頁連續的地址範圍,並不需要全部頁載入到內存中,當引用不在內存中的頁時,由操作系統將缺失的頁載入到內存,並重新執行失敗的指令

1.分頁

  • 內存管理單元MMU
    MMU
  • 虛擬地址構成了一個虛擬地址空間
  • 虛擬地址空間按照固定大小劃分成稱爲頁面的若干單元,在物理內存中對應的單元稱爲頁框
  • 頁面和頁框大小通常是相等的
    映射
  • 缺頁中斷:當MMU注意到某頁面沒有映射,於是CPU陷入到操作系統,這個陷阱稱爲缺頁中斷。操作系統會找到一個很少使用頁框並把它的內容存到磁盤(如果不在磁盤上),隨後把需要訪問的頁面讀到剛纔回收的頁框中,修改映射關係,然後重新執行引起陷阱的指令
  • MMU如何完成映射操作,以16個4KB頁面爲例,輸入16位虛擬地址,輸出15位物理地址,其中低12位爲偏移量,高四位爲頁號,第四位標記是否映射
    MMU操作

2.頁表

頁表的目的是把虛擬頁面映射爲頁框。從數學角度來說,頁表是一個函數,它的參數是虛擬頁號,結果是物理頁框號。這個函數可以把虛擬地址中的虛擬頁面域替換成頁框域,從而形成物理地址。

1)頁表項結構:
頁表項

  • 保護位:指出一個頁允許什麼類型訪問。最簡單的形式是一位,0表示讀/寫,1表示只讀。更先進的方法是3位,分別表示讀、寫、執行
  • 修改位:也稱髒位,表示這個頁面是否修改過,如果被修改過則必須寫會磁盤,若未修改過且磁盤存在副本則直接丟棄
  • 訪問位:在該頁被寫或讀時,標記該位,當發生缺頁中斷時,優先選擇未標記訪問的頁面
  • 高速緩存禁止位:禁止該頁面被高速緩存。對映射到設備寄存器而不是常規寄存器非常重要,保證硬件是不斷從設備中讀數據而不是從緩存中

2)加速分頁過程

主要考慮問題:
⑴虛擬地址到物理地址映射必須非常快
⑵如果虛擬地址空間很大,頁表也會很大
現象:大多數程序總是對少量的頁面進行多次的訪問

  • 轉換檢測緩衝區(Translation Lookaside Buffer 簡稱TLB):MMU中的硬件,將虛擬地址直接映射到物理地址,而不必在訪問頁表
    TLB

  • MMU使用 TLB時進行併發匹配,若不在則選擇一個表項清除,從內存中找到缺的頁表覆蓋

  • TLB軟失效:不在TLB而在內存,只需要更新TLB
  • TLB硬失效:不在TLB也不再內存,需要磁盤I/O找到該頁表,與軟失效處理時間相差百萬倍

3)針對大內存的頁表(巨大的虛擬內存)

1.多級頁表
如圖,32位的虛擬地址被劃分爲10位的PT1域、10位PT2域和12位偏移量
多級頁表

  • 引入多級頁表,爲了避免把全部頁表一直保存在內存中

2.倒排頁表:在實際內存中每一個頁框有一個表項,表象記錄哪一個(進程,虛擬頁面)對定位於該頁框

  • 爲了增強從虛擬地址到物理地址,需要使用TLB
  • TLB失效時搜索方法: 用虛擬地址建立一張散列表,當前所有在內存中的具有相同散列值的虛擬頁面被鏈接到一起
    倒排索引

3.頁面置換算法

當發生缺頁中斷時,操作系統必須在內存中選擇一個頁面將其換出內存,以便爲即將調入的頁面騰出空間。如果頁面在內存駐留期間修改過,就必須把它寫會磁盤;如果沒有修改過,則直接丟棄(因爲磁盤上的副本和當前一致,不需要寫回)

1)最優頁面置換算法

每個頁面都將該頁面首次被訪問前所需要執行的指令數目做標記,置換時選擇標記最大的頁面
#無法實現

2)最近未使用頁面置換算法NRU

用R位和M位在一個簡單的頁面置換算法:當啓動一個進程時,它的所有頁面這兩位都是0,R位定期地清零(如每次時鐘中斷時),當頁面進行修改時M位置1,被訪問時R位置1,則共有下面四類情況:
0,沒有被訪問,也沒有被修改
1,沒有被訪問,被修改
2,被訪問,沒有修改
3,被訪問,被修改
NRU算法隨機的從編號最小的非空類中挑選一個頁面淘汰

3)先進先出頁面置換算法FIFO

操作系統維護一個所有當前在內存中的頁面的鏈表,最新進入的頁面放在表尾,最久進入的頁面在表頭。當發生缺頁中斷時從表頭淘汰一個頁面,並把新載入的頁面加到表尾

4)第二次機會頁面置換算法

基於FIFO算法,檢查老頁面的R位,如果R位是0,那麼這個頁面既老又沒有使用,可以立即置換出去;如果R是1,就將R置爲0,並把該頁面放到鏈表尾端,修改裝入時間像剛裝入的一樣,然後繼續搜索。

5)時鐘頁面置換算法

由於第二次機會算法,經常在鏈表中移動頁面,效率不是很高。更好的辦法是:把所有的頁面都保存在一個類似鐘面的環形鏈表中,一個表指針指向最老的頁面。
時鐘頁面置換算法

6)最近最少使用頁面置換算法

LRU:在缺頁中斷髮生時,置換未使用時間最長的頁面。
硬件實現:
①硬件有一個64位計數器,每條指令執行完後自增1,每個頁表需有一個能容納這個計數器值的域。每次訪問內存後,將當前計數器值保存到頁面的頁表項中。一旦發生缺頁中斷,操作系統檢查所有頁表項中計數器的值,找到值最小的一個頁面,這個頁面就是最近最少使用的頁面。
②在一個有n個頁框的機器中,LRU硬件可以維持一個初始值爲0的nn 位的矩陣。當訪問到頁框k時,將k行的位都置爲1,k列都置爲0。在任何時刻二進制數值最小的行就是最近最少使用的。
LRU硬件

軟件實現:
①NFU:將每個頁面與一個軟件計數器相關聯,計數器的初值爲0。每次時鐘中斷時,由操作系統掃描內存中所有頁面,將每個頁面的R位加到計數器上。缺頁中斷時選擇計數器值最小的頁面。
②老化:基於NFU,在R位被加進來之前將計數器右移一位;其次將R位加到計數器最左端。
老化
老化算法有以下缺陷:
1.無法區分在一個時鐘滴答內,那個頁面被訪問的先後順序。
2.計數器位數只有有限位,當兩個頁面的計數器值一樣時只能隨機選擇一個。
往往,時鐘嘀嗒如果是20ms,8位一般夠用

7)工作集頁面置換算法

  • 請求調頁:頁面在需求時被調入,而不是預先裝入
  • 局部性訪問行爲:進程運行的任意階段,它都只訪問較少的一部分頁面
  • 工作集:一個進程當前正在使用的頁面集合
  • 顛簸:若每執行幾條指令程序就發生一次缺頁中斷,那麼就稱爲這個程序發生了顛簸
  • 工作集模型:設法跟蹤工作集,以確保讓進程運行以前,它的工作集就已在內存中了,目的在於大大減少缺頁中斷率
  • 預先調頁:在進程運行前預先裝入工作集頁面
  • 當前實際運行時間:一個進程從它開始執行到當前所使用CPU時間總數通常稱爲當前實際運行時間。
  • 生存時間:當前實際運行時間 減去 上次使用時間

基本思路,找出一個不在工作集中的頁面並淘汰它。
假定由硬件記錄R位和M位,每個時鐘滴答中有一個定期的時鐘中斷會用軟件方法清除R位,當發生缺頁中斷時:
掃描每個表
1. 若R位爲1,把當前實際時間寫進頁表項的“上次使用時間”域中,繼續掃描。
2.若R位爲0,且生存時間大於t,則說明不在工作集中置換該頁面,掃描繼續進行更新剩餘表項
3.若R位爲0,且生存時間小於等於t,則記住生存時間最長的頁面
4.若掃描結束後,R位都是0,則置換所記錄生存時間最長的頁面;若所有頁面都是1,則隨機選一個頁面置換,最好爲乾淨的。
工作集算法

8)工作集時鐘頁面置換算法

工作集時鐘
類似於時鐘算法,有一個循環鏈表和一個指針,每個頁表項有R和M位
當發生缺頁中斷時:
1.從當前指針開始,判斷R值時候爲1,若爲1,則更新上次使用時間,並將R位置爲0,繼續搜索
2. 若R爲0,且生存時間大於t,W位爲0,則置換出該頁
3. 若R爲0,生存時間大於t,W位爲1,寫回該頁面,指針繼續前進;爲了降低磁盤阻塞,只允許最大寫回n個頁面
4. 若掃描一圈回到起點,則有兩種可能:
4.1 調度過寫操作,置換第一個寫完成的頁面(由於磁盤驅動,未必是第一個調度的頁面)。
4.2 未調度過寫操作,隨機置換一個乾淨的頁面,若沒幹淨頁面,則選當前頁面寫回磁盤,乾淨後置換

9)頁面置換算法總結:

小結
化算法和工作集時鐘算法比較實用

4.分頁系統設計問題

1)局部分配策略與全局分配策略:

  • 局部配算法可以有效地爲每個進程分配固定的內存片段,全局分配算法可以在運行進程之間動態的分配頁框。全局分配策略更爲適宜
  • PFF缺頁中斷率算法:指出了何時增加或減少分配給一個進程的頁面數
    缺頁中斷率
    A :分配頁框太少,缺頁率過高
    B :分配的頁框太多
    A與B之間爲合理的缺頁中斷數

2)負載控制

  • 爲了減少競爭內存的進程數,將一部分進程交換到磁盤,並釋放他們所有的頁面
  • 在交換時,不僅要考慮進程的大小、分頁率也要考慮他的特性(如I/O密集或CPU密集)

3)頁面大小

大頁面:可能會有內部碎片(最後一個頁面將近一半是空的)
小頁面:需要更大的頁表,頁表的佔用和內存磁盤交換時間都需要更多
最優頁面大小公式 : P=2se
s: 進程平均大小
e: 每個頁表項需要多少字節
P: 頁面大小

4)分離指令空間和數據空間:
指令空間和數據空間

5)共享頁面

  • 每個進程在它的進程表中有兩個指針:一個指向I空間頁表,另一個指向D空間頁表
  • 兩個進程共享頁面時,各自有各自的頁表,但都指向相同的頁面(只讀的)
  • 寫時複製:當某進程需要對共享頁表進行修改時,觸發只讀保護,陷入內核,複製一份該副本,且該副本可寫

6)共享庫(win中稱爲dll):

  • 任何在目標文件中被調用了但是沒有被定義的函數稱爲未定義外部函數
  • 當一個共享庫被裝載和使用時,是以頁面爲單位裝載的,因此沒有被調用的函數是不會被裝在到內存中的
  • 編譯共享庫時,需要用一個特殊的編譯選項告知編譯器,不要產生使用絕對地址的指令,只能使用相對地址。只是用相對偏移量的代碼被稱作位置無關代碼

7)內存映射文件:

進程可以通過發起一個系統調用,將一個文件映射到其虛擬地址空間的一部分。

8)清除策略:

  • 分頁守護進程:後臺進程,大多數時候睡眠,但定期被喚醒檢查內存的狀態,若果空閒頁框過少,分頁守護進程通過預定的頁面置換算法選擇頁面置換出內存
  • 策略之一雙指針時鐘:前指針搜索髒頁面寫回磁盤,後指針正常進行頁面置換

9)虛擬內存接口:

  • 某些高級操作系統,程序員可以對內存映射進行控制,並通過非常規的方法增強程序行爲。
  • 例如允許兩個或多個進程共享同一部分內存

5.有關實現的細節:

1)有關分頁的工作

進程創建、進程執行、缺頁中斷和進程終止

2)缺頁中斷處理

1.硬件陷入內核,在堆棧中保存程序計數器。
2.啓動一個彙編例程保存通用寄存器和其他易失信息,這個例程將操作系統作爲函數來調用
3.找出缺少的虛擬頁面,通常硬件寄存器包含了這一信息,若沒有的話,操作系統必須檢索程序計數器,取出這條指令,用軟件分析這條指令。
4.檢查虛擬地址是否有效,並檢查存取與保護是否一致,若不一致則發出信號或殺死進程。若果地址有效並且沒有保護錯誤發生,系統檢查是否還有空閒頁框。如果沒有則用頁面置換算法淘汰一個頁面。
5.若果選擇的頁框髒了,安排該頁寫回磁盤,併發生上下文切換,掛起該缺頁中斷的進程,讓出資源直到傳輸結束。而該頁框被標記爲忙,不允許其他進程佔用。
6.一旦頁框乾淨,操作系統查找所需頁面在磁盤上的地址,發起磁盤操作將其裝入。同時,掛起該缺頁中斷進程。
7.當磁盤中斷髮生時,表明已裝入,頁表已經更新,頁框也標記爲正常狀態。
8.恢復發生缺頁中斷指令以前的狀態,程序計數器重新指向這條指令。
9.調度引發缺頁中斷進程,操作系統返回調用它的彙編語言例程。
10.該例程恢復寄存器和其他狀態信息,返回用戶空間繼續執行,好像沒發生過缺頁中斷一樣。

3)指令備份

同通過一個隱藏的內部寄存器。在每條指令執行之前,把程序計數器的內容複製到該寄存器上。這些機器可能會有第二個寄存器,用來提供哪些寄存器已經自動增加或者自動減少,以及增減數量的信息

4)鎖定內存頁面

兩種法法:
1.釘住:可以鎖住正在做I/O操作的內存頁面以保證它不會被移出內存。
2.在內核緩衝區中完成所有的I/O操作,然後再將數據複製到用戶頁面

5)後備存儲

在磁盤上分配頁面空間的最簡單的算法是在磁盤上設置特殊的交換分區,甚至文件系統劃分一塊獨立的磁盤
- 將整個進程映像複製到交換區,以便隨時可將所需內容裝入
- 將整個進程裝入內存,並在需要時換出
後備存儲

6)策略與機制分離

  • 基於Mach的分離方法
    MACH
    • 一個底層的MMU處理程序
    • 一個作爲內核一部分的缺頁中斷處理程序
    • 一個運行在用戶空間的外部頁面調度程序
  • 頁面置換算法的位置:外部頁面調度程序或者內核中
    • 放在外部需要某種機制把R、M位信息傳遞給外部頁面調度程序
  • 這樣分離主要優勢是更多的模塊化代碼和更好的適應性。主要缺點是多次交叉“用戶-內核”邊界引起的額外開銷,以及系統模塊間消息傳遞的額外開銷

6.分段


  • 每個段由一個從0到最大線性地址序列構成
  • 不同段的長度可以不同,且可以在運行期間動態改變
  • 一般它不會同時包含多種不同類型的內容,故不同的段可以有不同種類的保護
    分頁與分段比較
    1)純分段實現

直接在內存中劃分出不同大小的段,但是會產生外部碎片(棋盤形碎片),可以通過內存緊縮解決
純分段實現

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