1、從分層存儲器體系談起html
根據馮諾依曼計算機體系結構,計算機是以存儲器爲核心的。程序員
分爲五大部件:運算器、控制器、存儲器、輸入設備、輸出設備。編程
存儲器又包括寄存器、內存;CPU整合了寄存器、運算器、控制器;輸入輸出設備統稱I/O設備(外部存儲器即磁盤也屬於I/O範疇);小程序
內存(RAM)是計算機系統中重要的資源。內存屬於掉電易失性。緩存
通過整合一下,計算機大概分層這三大組件:CPU(還包括緩存Cache)、內存、I/O設備(磁盤屬於I/O設備的一種);數據結構
操做系統是怎樣對內存建立抽象模型而且怎樣管理內存呢?app
另外又不得不先提到一個概念存儲管理。人們提出了分層存儲器體系。優化
理想狀況下,人們但願有這樣一個存儲器:私有的、容量無限大、速度無限快,而且是永久性掉電不易失的。spa
很遺憾目前沒有這種的技術手段去實現這一目標。存儲系統層次存儲體系的提出就是解決這個矛盾的。操作系統
綜合考慮了容量、速度、成本三大因素。
以存儲器爲核心的計算機系統結構固然但願存儲器與運算器/控制器交換數據的速度越快越好,最好和運算器/控制器的運行速度同樣快。
顯然數據交換速度成了制約運行效率的重要因素。
寄存器的速度是最快的,而後是緩存的速度,再後面是內存,最慢的是磁盤。速度一次遞減;
可是越靠近CPU,速度越高,其成本越高,造價越高也就限制了容量的大小。
寄存器的容量最小,而後緩存大一些,但仍是不夠大,可能就幾十M。再後面是內存,能夠作到幾個G。最後是磁盤能夠作到幾百G;
不過利用程序的局部性原理,儘可能將CPU此時可能大機率訪問到的少許數據放到寄存器、緩存中。這樣就減小CPU和低速率存儲器的數據交換,也就能提升計算機總體的運行速率了。
這是利用這種局部性和存儲器分層體系,很好地解決了容量、成本、速度三者的矛盾關係。達到了某種程度的平衡。
那麼操做系統是如何適配這個存儲器分層體系的?->操做系統的工做就是將這個體系抽象爲一個有用的模型,並管理這個模型;
寄存器已經融入了CPU當中,固然是由CPU來管理。
高速緩存也是很底層的東西,直接交給硬件來完成就行了,也是融入到了CPU當中。
內存:通常是一個獨立的器件,掉電易失的。操做系統整理創建了對內存的模型來管理內存這一重要資源,而且不斷優化管理內存;-->也就是咱們要討論的內存模型了
磁盤:磁盤是大容量、低速、非易失性存儲器,操做也將它們作了抽象並加以管理。也就是文件系統了。
====================================================
2、爲何須要存儲器抽象,即爲何須要內存模型?
咱們來試想一個沒有存儲器抽象的計算機是什麼樣的?
那麼呈現給編程人員的存儲器模型就是一個簡單的物理內存。即從0到某個上限的地址集合。
每一個地址(映射)對應着一個可容納必定數目的二進制位的存儲單元,一般是8個,即一個字節。
a方案在當時被用在大型機和小型計算機上;
b方案被用在掌上電腦和嵌入式系統中;
c方案被用於早期的我的計算機。
a、c的方案缺點是用戶程序可能出現錯誤並摧毀操做系統。由於操做系統的地址空間是它們可以訪問獲得而且修改的。
另外不適用內存抽象的狀況下運行多道程序也是可能的。操做系統只須要把當前內存中全部內容保存到磁盤文件中。而後把下一個程序讀入到內存中便可。
在某一個時間內存中只有一個程序,那麼久不會發生衝突。這就有點相似於交換的概念了。
固然不採用交換也能夠實如今內存中運行多道程序,IBM 360早期模型是這樣解決的,內存被劃分稱爲2KB的塊,而後每一個塊被分配一個4位保護鍵。保存鍵存儲在CPU的特殊寄存器中。保護鍵來控制程序對內存的訪問。只有操做系統能夠修改保護鍵。若是一個運行中的進程其訪問保護鍵與其PSW碼不一樣的話,硬件就會捕捉到這一事件,防止其訪問這部份內存。可是這個方法仍是有缺陷,因爲程序自己引用的都是絕對物理地址,因此有可能跳轉到不正確的地方。IBM 360的補救措施是在程序裝載的時候,使用靜態重定位技術修改地址。可是這種方式又下降了程序裝載的速度。
在同時打開多個程序的狀況下,直接暴露物理地址給程序去尋址是十分危險的。它們很容易地破壞操做系統。
這就須要讓每一個程序都是用一套私有的地址空間來進行內存尋址,既能夠起到保護內存空間的做用,又不影響裝載速度。
爲了保證多個應用程序同時處於內存中而且不相互影響,須要解決兩個問題:保護、重定位。
一個更好的辦法是創造一種對內存的抽象->地址空間。
地址空間創造了一種抽象的內存。地址空間是一個進程可用於尋址內存的一套地址集合。每一個進程都有本身的地址空間。
而且這個地址空間獨立於其餘進程的地址空間。除了一些特殊狀況下,進程須要共享它們的地址空間外。
====================================================
3、如何實現內存抽象——內存是怎樣被管理的?
之前應用程序都是直接運行在物理內存上,訪問的都是物理地址,這會致使地址空間不隔離,容易形成內存崩潰的各類風險,甚至影響操做系統自己。並且程序運行時的地址就很不肯定。
因此對內存和使用和分配就很重要,如何將計算機上有限的物理內存分配給多個程序使用,以發揮出內存最大的效率?
靜態的重定位技術,即在裝載時肯定最終的物理地址,會致使裝載速率較慢的問題。
可是在多道編程環境下,沒法將程序老是加到固定的內存地址上,也就是沒法使用靜態地址翻譯。
所以,必須在程序裝載完畢以後才能計算物理地址,也就是在程序運行時才進行地址翻譯,這種翻譯稱爲動態地址翻譯,也就是動態重定位技術。
最初實現地址空間的方式是使用一種簡單的動態重定位技術。簡單來講就是把每一個進程的地址空間映射到物理內存的不一樣部分。
使用的經典方法是給每一個CPU配置兩個特殊的硬件寄存器——基址寄存器和界限寄存器;
當一個進程運行時,程序的起始物理地址被裝載到基址寄存器中,程序的長度被裝載到界限寄存器中。
例如當第一個程序運行時,基址和界限值分別爲0和16384;當第二個程序運行時,基址和界限值分別是16384和32768;
每次一個進程訪問內存,取一條指令,讀或寫一個數據字時,CPU硬件會把地址發送到內存總線前,自動把基址值加到進程發出的地址值上。而後檢查是否超出了界限寄存器的值。
若是超出了,就會產生錯誤並終止訪問。這種方法有個缺點就是每次訪問內存都須要進行加法和比較運算,效率是比較差的。
目前的解決方法就是在物理地址和應用程序之間增長一箇中間層——虛擬地址(Virtural Address)。
應用程序只須要關心虛擬地址空間,而後操做系統負責將虛擬地址映射成實際的物理地址。->用一個專門的硬件取管理地址的映射,這就叫作MMU(Memory Management Unit),一般被集成到CPU中,不做爲獨立器件存在。
只要妥善地控制這個虛擬地址到物理地址的映射過程,就能保證各個應用程序所訪問的內存空間跟另外一個程序相互不重疊。以達到應用程序之間的實際物理空間相互隔離的效果。
物理地址若是暴露給進程會使得它們很容易破壞操做系統,用戶程序能夠尋址內存的每一個字節。並且使用這個物理地址模型,要運行多個程序是很困難的。
多個應用程序同時處於內存,而且不互相影響,則須要解決兩個問題:保護和重定位。
一個很好的辦法就是對物理內存進行抽象,即內存模型,內存地址空間。每一個進程都有一個本身的地址空間。地址空間爲應用程序創造了一種抽象的內存。就像進程的概念創造了一類抽象CPU以運行程序同樣。地址空間就是一個進程可用於尋址內存的一套地址集合。
====================================================
4、談談存儲器管理
這裏的存儲器管理其實默認指狹義上的,即內存的管理+虛擬存儲器的管理。通常不包括磁盤管理(也就是文件系統),磁盤管理屬於操做系統的另外一大方面的知識。其實虛擬存儲器管理自己就是涉及到磁盤和內存之間的信息流動。這裏埋個引子,後面再展開討論。
內存管理無非就是把內存進行了抽象,抽象成某個內存模型。抽象的目的是爲了解決不抽象狀況下使用內存所存在的問題,有問題就有了改進的需求。
第2、三節的就是在討論爲何要進行內存抽象建模(存在的需求和問題)、如何進行抽象建模(地址空間);
在繼續討論存儲器管理的各項機制和策略以前,理解存儲器管理的需求是頗有用的。
主要有五大需求:
一、重定位 //第三節中講到的,程序中引用地址須要重定位才能訪問正確的位置且不干擾其餘程序;
二、保護 //多個程序運行時,必須保證相互獨立,不能互相干擾。尤爲是不能干擾到操做系統;
三、共享 //有時候有須要多個程序之間能有一塊共享的內存,你我均可以進行讀寫。這就是程序之間通訊的需求,在不違背一、2的狀況下在內存的管理過程當中又要保證必定的靈活性;
四、邏輯組織 //內存的地址空間被組織成線性的一維的地址空間。程序自己還能夠別劃分紅模塊。不一樣模塊的特性是不一樣的,有的只能讀、有的可讀可寫、還能夠考慮分開獨立編譯裝載。還得有機制可讓某個模塊被多個進程共享。那麼這個該邏輯組織如何設計來保證這個需求呢?
五、物理組織 //廣義上將計算機的存儲器分爲兩級內存(主存)和外存(輔存);外存就是磁盤,大容量,掉電不丟失可是讀寫速度慢。內存讀寫速度快,可是成本高,掉電丟失數據。大容量的磁盤適合長期存儲、小容量的內存適合保存當前要用的程序和數據。操做系統要關心的是內存和外存之間信息流的組織。讓程序員負責這個信息流是不切實際的,須要交給操做系統來辦。這裏也是操做系統存儲器管理的本質所在!!
====================================================
5、交換、分段和分頁
第二節講到了多道程序狀況下,直接訪問物理地址式的內存管理,存在的問題是重定位和保護!以及使用靜態重定位解決重定位問題,可是又致使程序加載太慢。
第三節講道理對內存進行抽象,創造了每一個進程獨有的地址空間。並使用虛擬地址訪問內存,由MMU轉換成物理地址。也就是在程序運行時才進行地址翻譯,這就是動態重定位技術。
咱們貌似解決了內存管理問題,實際上還有不少問題要解決。回頭再看看第四節講到的五大需求,都實現了嗎?
5.1交換管理
參考連接:基本內存管理:http://www.javashuo.com/article/p-hdabhfrm-hz.html
上面的連接裏有談到了物理內存如何分區 固定分區or非固定分區?空閒的空間如何管理?進程隨着運行過程當中須要增大空間該如何解決,且如何保證不影響到其餘進程?如何保證內存空間利用率高?分區致使的內存空間碎片化問題如何解決?
若是在多進程的環境下,有不少程序都要運行時,內存的空間不夠用怎麼辦?
咱們在第四節講到的虛擬存儲器管理就是指虛擬內存技術。其核心思想是把物理內存空間從主存擴大到磁盤空間中。 這就好像使得內存空間增大了同樣,其實是虛擬的。這實際上是利用率局部性原理,把程序不常常訪問的部分放置在虛擬內存(磁盤空間)中。
若是有須要再把虛擬內存中的程序換入到內存中,內存中不須要訪問得程序換出到虛擬內存中。這個過程交作交換。
可是因爲磁盤的數據訪問速度比內存慢,頻繁地進行交換必然致使程序運行速度降低。因此不能進行頻繁的換進換出操做。
目前咱們的內存管理都是以整個程序(即進程)爲單位進行換進換出,這會致使換進換出較爲頻繁。該如何解決這個問題?後面的分頁就是用來解決該問題的。
5.2 分頁管理
分頁的主要目的是提升內存的利用率。首先每塊頁分紅多大,分紅幾種,由硬件決定而後由操做系統選擇。虛擬地址空間按頁分割,進行映射。把經常使用的代碼和數據按頁裝載到內存中。把不經常使用的代碼保存在磁盤中。
以頁爲單位來存取和交換這些數據很是方便。硬件自己就支持這種以頁爲單位的操做方式。
把虛擬空間的頁映射到物理內存中的物理頁。沒有映射到內存中的虛擬頁,就留在了磁盤中,這部分虛擬頁叫做磁盤頁。而後咱們在須要進行交換時,按頁進行交換便可,及一旦發現虛擬頁在內存中沒有相應映射物理頁,就將該虛擬頁從磁盤換進到內存中,完成率映射。
例如程序運行過程當中,須要用到某虛擬頁VP1,可是VP1不在內存中,硬件就會捕捉到這個錯誤,即頁錯誤。而後操做系統接管進程,負責將VP1從磁盤中讀取出來,裝入內存。並將內存中物理頁和虛擬頁創建映射關係。
全部的硬件都採用一個叫MMU的部件來進行頁映射,Memory Management Unit 內存管理單元。頁映射模式下,CPU發出的是Virtual Address,程序看到的是虛擬地址。通過MMU以後,變成了Physical Address。通常MMU都集成在CPU內部,不做爲獨立組件存在。
因此這種分頁式管理很靈活,同時結合了交換的原理,按頁進行映射,暫時不將整個程序映射到內存中,部分虛擬頁留在磁盤中,根據須要交換進內存。並且利用局部性原理,減小沒必要要的交換。提升了內存的利用率(內存都是在跑有用到的代碼),又解決了空間不夠的問題(交換技術,分頁映射)。
在分頁系統的模型下,程序發出的虛擬地址分紅兩個部分:頁號+頁內偏移值;
虛擬地址到物理地址翻譯的過程就是,從虛擬頁到物理頁面的映射(Mapping)。MMU都要保存一個頁表,頁表存放的是虛擬頁到物理頁的映射。每當映射關係變化,頁表都會有更新(虛擬頁進出物理頁)。頁表是由硬件提供支持的,是一個硬件數據結構。因此對用戶來講是透明的,無需關心實現細節。
分頁的好處是:不會產生外部碎片(頁外碎片),整個內存空間利用率很高。並且進程所佔的物理上的內存空間能夠是不連續的,這很是好。很好地解決了兩個問題:1)空間浪費碎片化問題、2)程序大小受限問題,不受內存大小影響(分頁+交換共同實現的);
分頁技術的存在才能真真切切高效實現虛擬存儲器的效果,光有交換是不夠的。
到此咱們很好解決了五大需求中的重定位、保護、物理組織需求。
5.3 分段管理
分頁系統有個問題缺點:一個進程只能佔有一個虛擬地址空間。在此種限制下,一個程序的大小至多隻能和虛擬空間同樣大,其全部內容都必須從這個共同的虛擬空間內分配。
假如一個程序要佔用16G的內存空間,可是內存只有8G的話。只採用分頁系統的話,這個16G大小程序不管如何是沒法映射到8G內存當中的。怎麼解決這個問題呢?
分段管理就是將一個程序按照邏輯單元分紅多個程序段,每個段使用本身單獨的虛擬地址空間。
對於編譯器來講,咱們能夠給其5個段,佔用5個虛擬地址空間。一個段佔用一個虛擬地址空間,不會發生一個段增加時碰撞到另外一個段的問題。避免了空間不夠致使的編譯失敗。
總結來看,段是信息的邏輯單位。段的長度不固定,決定於用戶所編寫的程序。一般由編譯器在對源程序進行編譯時,根據信息的性質來劃分。段的目的是便於存儲保護和信息的共享;
分段系統能反映程序的邏輯結構,也便於段的共享和保護。這裏的分段管理又知足了保護和邏輯組織的需求。
加上分段管理以後,這時候咱們再來看MMU的虛擬地址到物理地址的轉化過程:
邏輯地址是段標識+段內偏移量。CPU經過查詢段表,將邏輯地址轉化爲線性地址。
而後若是開啓了分頁功能後,MMU還須要根據頁表來說線性地址轉化爲物理地址。
因此MMU這個硬件電路,它包含了兩個部件,一個是分段部件,一個是分頁部件。經過分段機制(邏輯地址轉化爲線性地址)、分頁機制(線性地址轉化爲物理地址),最終將邏輯地址映射爲物理地址。這裏咱們就看到了完整的虛擬地址到物理地址的地址空間轉化過程。分段和分頁對於程序來講都是透明的,在操做系統+硬件層面完成的工做。
5.4 段頁式管理
頁是信息的物理單位;分頁是爲了實現離散分配的方式,以消減內存的外碎片(可是可能有內碎片,由於頁可能填不滿),提升內存的利用率。頁的大小固定,且由系統決定。機器硬件實現將邏輯地址劃分紅頁號和頁內地址兩部分。頁是爲了管理主存的方便而劃分的,對用戶是透明的;
段是信息的邏輯單位;段的長度不固定,決定於用戶所編寫的程序。一般由編譯器在對源程序進行編譯時,根據信息的性質來劃分。段的目的是便於存儲保護和信息的共享;
段頁式存儲管理:分頁系統可以有效提升內存的利用率,分段系統能反映程序的邏輯結構,便於段的共享和保護。將分頁和分段兩種存儲方式結合起來,就造成了段頁式存儲管理方式。
程序員按照分段系統結構把地址分爲段號+段內位移量;
地址變換機構將段內位移量分解爲頁號+頁內位移量;
系統爲每一個進程設置一個段表,包括每段的段號,該段的頁表起始地址和頁表長度。每一個段有本身的頁表,記錄段中每一頁的頁號和存放在主存中的物理塊號。
====================================================
6、談談虛擬內存
虛擬內存使得用戶感受內存獲得了增長。實際上虛擬內存其實就是存放在磁盤中的一些頁文件,或者叫磁盤頁。
CPU是不會直接讀取磁盤中的這些磁盤頁的。必須把磁盤頁交換進內存中才行。這個過程也是位於磁盤中的虛擬頁創建與內存中物理頁映射的過程。
====================================================
相關連接:
內存系統爲何要分段: https://blog.csdn.net/f905699146/article/details/72887398
cpu訪問內存爲何要分紅各類段:https://new.qq.com/omn/20180118/20180118G048AJ.html
計算機層次化存儲體系:https://blog.csdn.net/guohexiaoming/article/details/89209061
計算機體系結構和存儲分層體系:https://blog.csdn.net/qq_42381849/article/details/90231377
內存管理下-段式內存管理:http://www.javashuo.com/article/p-bcvhnmzz-hn.html