作業系統記憶體管理概述

FreeeLinux發表於2017-01-06

概述

儲存器分為記憶體和外存。主存就是記憶體,外存也稱為輔存,就是磁碟,磁帶機等外部裝置。主存是和CPU通過匯流排相連的,CPU執行指令需要從記憶體(即主存,後文同理)從中訪問指令和資料。記憶體被分為了兩部分,一部分是系統區(核心子程式佔用),一部分是使用者區(使用者程式、資料)。通常主存的低地址段分給作業系統,高地址段分給使用者。我們今天的問題是,作業系統磁碟中的資料怎麼裝載進記憶體中呢?

對於系統區,當機器開機時,系統上電,通過硬體會到系統的BIOS中,BIOS中會呼叫一段程式,檢測硬體有無錯誤,同時到磁碟的一個固定的位置,把作業系統的一些關鍵的核心程式碼(僅僅是部分程式碼)讀入到記憶體中的系統區;對於使用者區,怎麼樣分配?怎麼回收?怎麼使得記憶體利用率最大?記憶體中同一時刻的程式個數決定作業系統的併發度,那麼採取什麼樣的記憶體分配策略增大作業系統的併發度?所以,本篇部落格將對這些問題進行分析。

源程式如何裝入記憶體

一個源程式怎麼裝載入記憶體呢?首先得編譯變成目標模組,源程式就變成若干個相對0地址開始編址的程式段(邏輯地址),由於每個目的碼都是從0開始編址,所以它們目前並不能執行。下一步要進行連結,把它們合併為一個整體,最後才能裝入進入記憶體之中。

那麼這個過程看似簡單,怎麼樣把目標模組連結起來?是編譯時進行連結還是在執行時連結?編譯時一般不知道指令會放在記憶體中什麼地方(僅知道邏輯地址),可能要靠裝入時決定。如果在裝入時決定指令要存放在記憶體某個地址(實體地址),相當於該程式地址被固定了,那麼該程式就不能移動了!除此之外,還有對於共享的程式段的問題(比如某個 function 多個程式都共享),那麼難道需要每個程式把它都裝入一遍嗎? no,肯定不需要。所以,程式的裝入和連結的過程,和記憶體分配和管理有緊密的關係。

記憶體管理的需求

重定位

為什麼需要重定位?有兩個原因:

1. 多個程式同時在記憶體中,互相 "擠兌",地址無法事先確定。
2. 活動程式需要換入換出記憶體,如果地址換入還要保持先前相同的地址,這會是一個極大的限制。

因此,作業系統必須能夠以某種方式把程式程式碼中的記憶體訪問(邏輯地址)轉換成實際的實體地址,並反映程式在記憶體中的位置,也就是具備重定位的能力。

保護

程式必須受到保護,避免其他程式非法讀寫自己的記憶體單元。並且,由於重定位,無疑增加保護的難度。因為程式在記憶體中的位置是不可預測的,一次編譯時不可能通過查絕對地址來確保保護。並且,大多數程式語言允許執行時進行地址的動態計算(如陣列下標和指標)。因此,必須在執行時檢查程式所有的記憶體訪問,確保程式不會越界訪問。

注意:記憶體保護的需要必須由處理器(硬體)來滿足,而不是由作業系統(軟體)來滿足,只是因為作業系統不能預測程式可能產生的所有記憶體訪問;即使可以預測,提前審查每個程式中存在的違法訪問也是非常費時的。所以,處理器必須具備保護的能力。

共享

多個程式正在執行同一程式,那就記憶體中只儲存一份,讓它們共享吧 :)

邏輯組織

主要體現在分段技術上,後面分析。

物理組織

作業系統儲存器物理上分為兩級,記憶體和外存。在這兩級儲存器間移動資訊的任務就是作業系統的責任了,這就是儲存管理的本質。(總不讓程式設計師程式設計時記憶體不足去換入換出或者覆蓋吧 :))

內外存的資料交換

1.使用者程式自己控制方式。典型例子是覆蓋,早期主存擴充方式,需要程式設計師清楚瞭解程式結構,程式調入記憶體次序,難度較大,且不能實現虛擬儲存器。
2.作業系統控制方式
    交換技術: 交換技術的目的也是為了緩解記憶體不夠大的矛盾。它利用外存空間(程式交換區),通過對程式實體的整體交換,來滿足記憶體需求,實現多道程式執行。特點:打破了程式執行的駐留性
    請求調入方式:程式執行時,如果要訪問的程式段或資料段不在記憶體(此時會觸發缺頁異常),則作業系統自動地將有關的程式段和資料段調入記憶體。
    預調入:由作業系統預測在不遠的將來將會訪問到的那些程式段和資料段部分,並在它們訪問之前系統選擇適當的實際將它們調入記憶體。

相關文章