計算機系統012 - 操做系統以內存管理

前面兩篇中介紹了進程並行和死鎖(死鎖一章的內容寫完時也以爲比較水,我的也不太滿意),一般進程自己包括代碼、數據、運行時信息以及棧,所以進程運行過程當中,不只須要使用到CPU時間,還須要有內存、I/O等設備的參與。本篇就從內存管理的角度來對操做系統中進程運行作進一步說明。 算法

1. 內存管理

所謂內存管理,其最基本的操做就是由CPU把程序裝入到內存中執行。遠古批處理時代,進程獨佔各類計算機資源依次執行,所以只要小於可用內存總大小(主要是除去操做系統自己所佔內存)的進程都可加載運行。隨着操做系統的發展,提升CPU利用率和下降平均響應時長成了兩大主流方向。前面的文章中反覆提到提升CPU利用率的最有效方法就是加載多個進程到內存中,經過在一個進程執行I/O操做期間切換至另外一進程,避開阻塞等待。也就是說,同一時刻加載入內存空間的進程數越多,可供選擇的進程就越多,就越有機會避開I/O操做等待時間,那麼,剩下的問題就是,該如何增長加載入內存空間的進程數。 性能

可加載到內存空間的進程總數受到兩方面影響: 動畫

  • 物理內存總量:硬件上內存空間總量老是有限的,如早期計算機只有256MB內存
  • 單個進程佔用內存空間數:爲了完成更復雜的功能、呈現更好的視覺效果等,程序日益複雜,運行所需內存空間與日俱增

簡而言之,內存與進程間的態勢是供不該求。針對問題找方法,可選的解決方法有以下兩種: 編碼

  • 增大物理內存總量
    增大物理內存總量,需考慮硬件技術以及經濟能力兩方面。硬件技術發展總有其時代侷限性,即便到今天,民用計算機中單條內存16GB的容量已是很高端的了,而這一級別的內存條目前均價爲600RMB左右。以臺式機爲例,插滿4根組成64GB須要成本約2400RMB,價格不菲。並且這只是內存而已,畢竟計算機總體性能還和其餘如CPU、硬盤、顯卡等各大燒錢部件息息相關。所以無論是從硬件技術仍是經濟效益來考慮,增大物理內存總量這條路潛力頗有限。 操作系統

  • 下降單個進程運行所需內存空間
    能用軟件實現的功能,只要對效率上要求不十分嚴格,實現起來的靈活性和性價比要比單純擴展硬件要高得多,對於內存的使用也一樣如此。要想下降進程所需內存空間,只有一種方法,那就是只加載進程中當前可能執行到的部分cdn

1.1 局部性原理

從物理學上講,局部性原理認爲一個特定物體只會受到其直接相關環境影響。而對應到計算機系統中,硬件只會與其有直接電氣線路相連的其餘硬件交互,軟件程序中,每個指令也只會與其附近一段區域內代碼相關聯。講句人話就是,硬件交互須要電氣接觸,軟件執行一般只會牽扯到附近代碼,畢竟編碼過程當中自己就會將問題進行模塊分解。對比例證,閱讀理解文學做品時對於單句的理解需結合上下文,商品使用說明書一樣是分模塊說明的。 blog

局部性原理爲前一小節提出的「只加載進程中當前可能執行到的部分」的解決方案提供了理論支撐。雖然進程中包括了不少代碼和數據,但執行過程當中CPU是以順序執行讀取到的指令的,假如能夠保證每條指令只和附近一些指令相關,那就能夠只加載必定量的指令就能夠實現進程內部的順序執行,對於數據部分也是一樣的道理。實際應用中,如如今的遊戲程序,動輒十幾GB、甚至幾十GB,其實內部大可能是動畫CG。若是執行程序的前提是必須所有加載,那麼不多有硬件可以成功運行該遊戲程序;但基於局部性原理,運行時只加載當前章節或場景必需的代碼數據便可,只有當須要切換到其餘章節、場景時,再動態加載對應代碼數據。 遊戲

1.2 重定位

雖然根據局部性原理,使得同時能夠加載入內存的進程總數有所提高,但內存總量始終是不能改變的,而進程運行過程當中也隨時可能增減所需內存。要想保持進程總數甚至加載更多進程,在有增的同時就勢必有減。然而增減終歸要有源頭,而這個源頭就是輔助存儲設備,也稱爲二級存儲器,典型設備爲磁盤Disk。 進程

當內存中沒有富餘內存空間時,就必須將一部分進程使用到的內存空間減小。這些空間可能包括進程存儲原始數據的空間,也有可能包括運行時動態信息的空間,爲了再當從新切換回這些進程時能夠正確執行,如同進程切換同樣,須要將所減小的空間進行存儲,而存儲的位置只有容量更大的磁盤空間。從內存保存到磁盤、或是從磁盤從新加載回內存的操做就叫作交換ip

內存管理中,只保證提供內存空間,並不保證每次提供的內存空間在物理上位置都同樣。例如,進程被交換到磁盤後再次加載,所加載到的位置幾乎不會與被交換出內存時所處的位置同樣。這也是爲了保證各進程所需的不一樣內存空間總數同時,儘量減少外部碎片(可視爲進程間鏈接處不能使用的空間)。既然位置發生了變化,但進程還要繼續執行,那就只能經過重定位技術來Cover掉這個差別。


單純講重定位會過於抽象,要理解這個概念,首先要對幾種地址類型進行區分:

  • 物理地址/絕對地址,是數據在內存中的實際位置,一般物理地址是一組連續線性遞增的地址空間
  • 邏輯地址,指與當前數據在內存中的物理分配地址無關的訪問地址,在執行對內存的訪問以前必須先把它轉換成物理地址
  • 相對地址,相對於某已知點(一般是程序的開始處)的存儲單元

因爲不一樣操做系統對於進程的具體定義各有差別,內核所使用的調度策略也有所差異,所以進程所能分配到的地址以及地址空間位置的關係也均有所不一樣。這樣一來,進程運行過程當中,天然不能經過物理地址來查找指令、數據等信息,爲了不硬件地址對其影響,進程中使用邏輯地址做爲分佈依據。要想實現這項功能,操做系統中就必須維護一份邏輯地址與物理地址間的映射表,從而使得操做系統能夠將進程運行時的邏輯地址轉換爲物理地址,進行存取

1.3 典型進程執行過程

綜合前文所述,如在進程執行中選擇只加載(或是儘量少)必需代碼、數據,那麼典型進程執行過程以下:

  • 操做系統讀取包含程序開始處的一些字節
  • 因爲進程剛執行,只有小部分在內存中,所以會由於沒法讀取到後續指令、數據而觸發大量中斷
  • CPU收到中斷後移交控制權給操做系統
  • 操做系統肯定數據在磁盤上的位置
  • 讀取數據至內存中
  • 返回至原進程,繼續執行

這樣一段時間後,經過預測等CPU技術,將進程可能執行的指令數據提早加載到內存中,中斷將不多觸發,總體執行過程趨於穩定,直到進程執行結束。

2. 交換單元

前一節中總體介紹了內存管理中增長內存中可加載進程總數的有效解決方法,但對於交換的具體細節並無作過多說明,這裏就從交換單元的角度來看看交換過程相關問題。

經過硬件部分的知識咱們瞭解到,物理內存是線性地址空間,而大多數程序是以模塊形式組織,所以從邏輯上來說,以模塊形式組織會更有利於組織代碼和數據。一般操做系統佔據了內存中的某些固定部分,內存的其他部分可供多個用戶進程使用,稱爲用戶空間。而根據用戶空間從邏輯地址到物理地址的轉換單元粒度大小,可分爲以下三類。

2.1 分區

一樣是遠古時期,主要是使用分區技術進行內存管理。經過將內存空間分區,造成若干邊界固定的區域。進程加載時,選擇大於或等於所需空間大小的分區進行裝載。所以分區技術中,進程加載匹配的單位是分區,進程和分區是是一對一的關係

分區技術中交換的單位是分區,和其餘技術同樣,放置時使用到的放置算法主要有三種:

  • 最佳適配,選擇與要求大小最接近的塊
  • 首次適配,從開始掃描內存,選擇大小足夠的第一個可用塊
  • 下次適配,從上一次放置的位置開始掃描內存,選擇下一個大小足夠的可用塊

相較而言,分區技術存在的最大問題是粒度過大,因爲進程所需空間值域較廣,很容易引入內部(固定分區特有)、外部碎片,形成內存空間上的浪費。雖然經過壓縮等技術能夠適當減緩,但效率上仍然不十分可觀,所以目前分區技術已基本再也不使用。

2.2 分頁

有了分區的前車可鑑,那麼分頁技術就適當下降了單元粒度,此時一個進程再也不對應一個完整分區,而是對應多個頁。進一步說明以前,首先了解一下以下概念:

  • 頁(page)
    必定大小字節數內存單元,屬於邏輯單元。進程中全部代碼、數據等信息均按頁進行存儲,屬於邏輯組織形式。每一個頁有頁碼及其餘信息。

  • 頁框(page frame)
    對應頁字節數的物理內存,屬於物理單元,是實際存在於物理內存中的可用地址單元。頁框至關於頁的容器,進程運行過程當中,可能會動態加載不一樣頁進入頁框,CPU則直接對頁框進行存取。

  • 頁表(page table)
    既然有頁和對應頁框,那就必須有映射表將二者聯繫起來,而頁表就是頁和頁框之間的映射表。換言之,知道頁就能夠查詢到頁框,知道頁框,也能夠查詢到對應頁。

頁表存在必要性還有一個角度能夠理解,因爲單元粒度變小,那麼單元總數就上升了。爲了便於管理,對於總數衆多的事物,一般會採用分級管理的方法。以學校對於學生的管理爲例,一般會劃分爲校長、年級主任、班主任、班長、組長等層級。對於內存也一樣如此,經過將每8個bit組織爲一個字節,每多少字節組織爲一頁,劃分層級。操做系統爲每一個進程維護一個頁表,頁表給出該進程的每一頁對應的頁框的位置。對於每一頁中的位置,則進一步使用偏移量來表示。

當進程嘗試引用不在內存中的頁時,CPU會斷定爲頁錯誤,並將控制權暫時從進程移交到操做系統,而操做系統則負責:

  • 肯定數據在磁盤上的位置
  • 從內存中獲取一個空的頁框做爲數據容器
  • 加載所需數據至可用頁框
  • 更新新頁框至頁表
  • 返回至原進程,繼續執行形成也頁錯誤的指令

第二步中,如全部頁框均處於使用中狀態,則操做系統必須選擇一個頁框進行重用。如被交換頁框是被其餘進程動態加載以存儲數據、或是加載進內存後被進程修改過,則必須寫回到磁盤中。操做系統選擇頁框進行重用的方法稱爲頁替換算法,它關係着總體效率。頁替換算法有不少側重性,如最少使用、最先加載等,歸根結底,沒有適用於全部場景的算法,但經過不斷增長有價值的基礎信息,是可使得頁替換更加精確地保證某些特性的。

2.3 分段

分段技術與分頁的區別倒不在單元力度上,而是邏輯組織形式。分頁的最終單位是頁,而分段最終單位是段。對於硬件電路而言,可能區別不是很大,但對於程序開發而言,有更貼近天然語言表達方式的優勢。

分段技術將計算機內存分解爲各段,每一個段有起始地址和長度,以及一系列權限信息(如讀、寫、執行等)。而一樣地,將進程代碼數據等爲幾個段,邏輯地址一樣由段號和偏移量組成。

和分頁對應,分段時操做系統也需維護一個段表。總的來說,分頁和分段有兩個特色:

  • 進程中全部內存訪問都是邏輯地址,這些邏輯地址在運行時動態地被轉化成物理地址
  • 一個進程能夠劃分紅許多塊(頁和段),執行過程當中,這些塊不須要連續地位於內存中。

3. 虛擬內存

虛擬內存的原理是使用二級存儲器以使得程序可使用超出物理內存大小的內存資源,撕掉包裝,就是說用一部分低速的磁盤空間,充當內存空間,從而僞裝每一個進程都有不少內存空間可使用。

若是說內存是實實在在存在的內存單元,那麼磁盤上的就是虛擬存在的內存單元,所以將這二者合稱爲虛擬內存。有人可能比較擔憂,增長了磁盤和內存間數據交換會不會下降了CPU執行效率,好比說若是實現加載了進程所有指令等,那麼執行時只須要直接從內存中讀取並依次執行便可,但如今,可能須要等待部分不存在於內存中的指令從磁盤讀取,勢必會增長指令週期數而拖慢整個CPU。那麼只能說,影響確定有,但不大,並且能夠經過算法策略進行最小化。回想一下計算機系統整個存儲分級機制,一樣也是從快到慢,從小到大,但CPU並無由於內存的低速而變得慢起來。

這些算法策略(以分頁爲例)主要包括以下幾類:

  • 讀取策略
    肯定一個頁什麼時候取入內存,經常使用的方法是請求分頁和預先分頁。

    • 請求分頁,只在訪問到某頁中單元時纔將該頁取入內存
    • 預先分頁,利用大多數輔存設備特性,一次性讀取許多連續頁以平均讀取時間
  • 放置策略

  • 置換策略

這裏不對具體算法策略進行展開,畢竟不是本系列文章的初衷,也容易暴露本人算法渣渣的面貌。

4. 總結

行文至此,能夠整理出操做系統的內存管理取決於三個基本方面的選擇:

  • 是否使用虛存技術
  • 使用分頁仍是分段,或是兩者結合
  • 爲各類存儲管理特徵採用的算法

前二者取決於使用的硬件平臺,所以早期系統未提供虛存是由於CPU不支持分頁或分段。因此仍是那句話,理解一個事物最好追溯其本源,萬物存在皆有理,你若是不能理解到其中理,極可能只是由於你沒有充分了解其歷史侷限性。

同時,也但願本篇中講解到的內存管理方面內容可以給你們造成一個較爲清晰的概念,結合前文所述電學、硬件、操做系統等知識,融會貫通,有所感悟,謝謝!

相關文章
相關標籤/搜索