操作系統精髓與設計原理--虛擬內存

概述

        爲了更高效的利用處理器和IO設備,需要在內存中運行更多的進程;同時使程序開發時不受內存大小的影響,而解決這兩個問題的方法是使用虛擬內存技術。

        通過虛擬內存技術,將本要分配在實內存的進程,可以部分分配到磁盤上,當需要訪問時再將其換出到實內存裏。使用邏輯地址訪問訪問,在運行時轉爲實地址,讓使用者感覺使用的是更大的一片內存。而分配在磁盤的存儲空間,被稱爲虛擬內存。

        如果不使用虛擬內存技術,當沒有使用覆蓋技術時,就必須將進程的所有頁存儲在內存裏;而使用虛擬內存時,可以將當前運行的進行頁存儲到內存頁框裏,非運行的進程頁存儲到磁盤裏,在需要時讀入到內存(當將一頁讀入到內存時,就可能將一頁寫入到內存裏)。虛擬存儲技術可以和分段、分頁的內存管理技術相結合,具體有虛擬分頁、虛擬分段等內存分配方式。(關於覆蓋技術和交換技術的區別見此

        支持虛擬內存技術的兩個基本方法是分頁和分段。對於分頁,每個進程化分爲相對比較小且大小固定的頁,而分段可以使用大小可變的塊。還可以把分頁和分段組合在一個內存管理方案中。

        由於可以通過邏輯地址訪問,同時在運行時轉化爲實地址,因此虛擬內存技術允許一個進程分佈在不連續的內存塊裏,並且可以隨時間的變化而改變,甚至可以運行時不需要將所有的塊存儲在內存裏。

        虛擬內存管理方案要求硬件和軟件的支持。硬件支持由處理器提供,包括把虛擬地址動態轉換爲物理地址,當訪問的頁或端不在內存時產生一箇中斷。這類中斷觸發操作系統中的內存管理軟件。

使用非虛存與虛存的分頁、分段內存管理技術的對比

簡單分頁虛存分頁簡單分段虛存分段
內存被劃分爲成大小固定的小塊、稱作頁框內存被劃分爲大小規定的小塊,稱作頁框內存未被分配內存未被分配
程序被編譯器或內存管理系統劃分成頁程序被編譯器或內存管理器系統劃分成頁由程序員給編譯器指定程序段由程序員給編譯器指定程序段
頁框內有內部碎片頁框內有內部碎片沒有內部碎片沒有內部碎片
沒有外部碎片沒有外部碎片有外部碎片有外部碎片
操作系統必須爲每個進程維護一個頁表,以說明每個頁對應的頁框操作系統必須爲每個進程維護一個頁表,以說明每個頁對應的頁框操作系統必須爲每個進程維護一個段表、以說明每一段中的加載地址和長度操作系統必須爲每個進程維護一個段表、以說明每一段中的加載地址和長度
操作系統必須維護一個空閒頁框列表操作系統必須維護一個空閒頁框列表操作系統必須維護一個內存中空閒的空洞列表操作系統必須維護一個內存中空閒的空洞列表
處理器使用頁號和偏移量來計算絕對地址處理器使用頁號和偏移量來計算絕對地址處理器使用段號和偏移量來計算絕對地址處理器使用段號和偏移量來計算絕對地址
當進程運行時,所有頁必須都在內存中,除非了覆蓋技術當進程在運行時,並不是所有頁都要在頁框中,只有需要時纔讀入頁當進程在運行時,所有段都必須在內存中,除非使用覆蓋技術當程序運行時,並不要求所有的段都必須在內存中,只在需要時纔讀入段

把一頁讀入內存可能需要把另一頁寫到磁盤
把一段讀入內存可能需要把另一段或幾個段寫出到磁盤

操作系統對內存管理支持的相關設計問題

讀取策略:

        進程頁可以在請求時讀取;或者使用預先分頁策略,使用的簇的方式一次讀取許多頁

  • 請求分頁:只有當訪問到某頁的一個單元時纔將該頁取入內存。這個策略並是不最優有的,因爲存在下述情況:一個進程第一次啓動時,會在一段時間出現大量的缺頁中斷;當越來越多的頁被取入後,局部性原理表明大多數將來訪問的頁都是最近讀取的頁。在一段時間後缺頁率會逐漸減少,缺頁中斷的數目會降低。

  • 預先分頁:讀取的頁並不是缺頁中斷請求的頁,該策略利用了大多數輔存設備(如磁盤)的特性,這些設備有尋道時間和合理的延遲。如果一個進程的頁被連續存儲在輔存中,則一次讀取許多連續的頁比隔一段時間讀取一頁更有效。如果大多數額外讀取的頁沒有被引用到,則此策略是低效的。當進程第一次啓動時,可以使用預先分頁策略,在此情況下程序員必須以某種方式指定需要的頁;當發生缺頁中斷是也可以採用預先分頁策略,由於這個過程對程序員是不可見得,因而表現的更可取一些,但預先分頁的實用工具程序還沒有建立。

  • 預先分頁和交換是不同的:當一個進程被換出內存並且被置於掛起狀態時,它的所有駐留頁都被換出,當該進程被喚醒時,所有一切在內存的內都被重新置回到內存中。

放置策略:

        決定一個進程塊駐留在實存的什麼地方。當在純粹的分段系統中,放置策略並不是重要的設計問題,因爲有最佳適配、首次適配等都可以選擇。但對於在純粹的分頁系統或段頁式的系統,如何放置通常沒有關係的,因爲地址轉換硬件和內存訪問硬件可以以相同的效率爲任何頁框組合執行它們的功能。

        有一個關注放置問題的領域是非一致性存儲訪問(NonUiform Memory Access,NUMA)多處理器。在非一致性存儲訪問多處理器之中,機器分佈的共享內存可以被該機器的任何處理器訪問,但訪問某一特定的物理單元所需要的時間隨處理器和內存模塊之間距離的不同而改變。因此其性能很大程度上依賴於數據駐留的位置與使用此數據的處理器的距離。對於NUMA系統,自動放置策略希望能把也分配到能夠提供最佳性能的內存。

置換策略

        用於處理在必須讀取一個頁時,要置換內存中的哪個頁的情況,其目標是移除最近不可能訪問的頁。由於局部性原理,最近訪問歷史和最近將要訪問的模式間有很大的相關性,因此大多數策略都基於過去的行爲來預測將來的行爲。

        置換策略有許多使用的算法,要注意的是關於置換策略的一個約束:內存中的某些頁框可能是被鎖定的,即當前保存在該頁框的頁就不能被置換。大部分操作系統內核和重要的控制結構就保存在鎖定的頁框中,同時I/O緩衝區和其他對時間要求嚴格的區域頁框內鎖定在內存的頁框中。鎖定是通過給每個頁框關聯一個LOCK位實現的,這一位可以包含在頁框表和當前頁表裏。

        基本算法:

  • 最佳(OPT):選擇下次訪問距當前時間最長的頁,此算法導致的缺頁率最低,但由於操作系統要知道將來的事件,因此是不可能實現的,屬於理想模型,可以作爲一個標準來衡量其他算法性能。

  • 最近最少使用(LRU):置換上層使用距當前最遠的頁。由局部性原理可知,這也是最近最不可訪問到的頁。而實際上LRU策略接近與OPT,問題在與比較難實現,一種方法是給每一頁添加一個最後一次訪問時的時間標籤,必須在每次訪問存儲器時,都更新這個標籤;另一種方法是維護一個關於訪問頁的棧,兩者的開銷大。

  • 先進先出(FIFO):把分配給進程的頁框看做是一個循環緩衝區,按循環的方式移動頁。所需要的只是一個指針,且讓指針在該進程的頁框中循環,此策略實現起來非常簡單。該此策略所隱含的邏輯是置換駐留在內存中時間最長的頁,到現在可能不會再用到,但此推測常常錯誤,因爲經常會有一部分程序或數據在整個程序的生命週期中使用頻率都很高的情況,此時該策略會反覆地需要被換入換出。

  • 時鐘:最簡單的策略需要給每一頁框關聯一個附加位,稱爲使用位。當某一頁首次轉入內存中時,將該爲置1,當被訪問到時(產生缺頁中斷之後),同樣被置爲1。用於置換的候選頁框集合(當前進程或整個內存)被看着一個循環緩衝區,並有一個指針與其相關聯。當要一頁被置換時,指針被設置爲指向緩衝區的下一頁框;當要置換一頁時,操作系統掃描緩衝區,以查找使用位被置爲0的頁框。如果掃描是遇到使用位爲1的頁框時,將其置爲0;如果開始時所用頁框都爲0,則置換遇到的第一個頁框;如果所有頁框的使用位都爲1,則掃描一遍後將所用使用位置爲0,並置換剛開始指向的頁框。類似與FIFO,不同的是該策略跳過使用位爲1的頁框。類似的有其他時鐘策略的變種,如添加策略位數目的使用(添加一個修改位,如果修改則在寫入到輔存前不能被置換到內存;優先將未修改的頁框置換出內存,由於沒有被修改則不需要寫回到輔存裏)。

駐留集策略

        對於分頁式的虛擬內存,在準備執行時,不需要也不可能把一個進程的所有頁都讀取到內存。因此操作系統必須決定要讀取多少頁,即給特定的進程分配多大的內存空間。這要考慮以下因素:

  • 分配給一個進程的存儲量越小,則任何時候駐留在內存的進程數越多。增加了操作系統至少找到一個就緒進程的可能性,從而減少了由於交換而消耗的處領取時間

  • 如果一個進程在內存中的頁比較少,雖然有局部性原理,但缺頁率任然較高。

  • 給特定進程分配的內存超過一定大小後,由於局部性原理,缺頁率沒有明顯變化。

        基於這些因素,操作系統常常使用兩種策略:

  • 固定分配策略:爲一個進程在內存中分配固定數目的頁框用於執行時的使用。此數目在最初加載(進程創建)時決定的,根據進程的類型(交互、批處理、應用類)或者基於程序員或系統管理員的需求來確定。一旦缺頁中斷出現,該進程的一頁必須被它所需要的頁面置換。

  • 可變分配策略:分配給進程的頁框在該進程的生命週期中不斷髮生變化。如果一個進程的缺頁率一直高,則該進程的局部性比較弱。應該多分配頁框以減少缺頁率;如果一個進程的缺頁率特別低,則其局部性原理比較強,可以在不會明顯增加缺頁率的前提下減少分配給它的頁框。雖然開上去性能更優,但難點在於要求操作系統評估活動進程的行爲,必然需要操作系統的軟件開銷,同時依賴於處理平臺提供的硬件機制。 置換範圍有區分:

  • 局部置換策略:僅僅在產生此次缺頁的進程駐留頁中選擇置換頁。

  • 全局置換策略:在內存中所以未被鎖定的頁作爲置換的候選頁。

        兩種策略的關聯: 使用固定分配策略,則意味着使用局部置換策略:爲保持駐留集大小固定,從內存中移出的一頁必須由同一個進程的另一個頁置換。因此有以下三種組合:

分配策略局部置換全局置換
固定分配一個進程的頁框數是固定的;從分配給該進程的頁框中選擇被置換的頁不可能
可變分配分配給一個進程的頁框數可以不斷地變化,用於保存該進程的工作集合;從分配給該進程的頁框中選擇被置換的頁進程駐留集的大小不斷變化;從內存中的所有可用頁框中選擇被置換的頁

清除策略

        與讀取策略相反,此策略用於何時將一個被修改過得頁寫回到輔存。有兩種選擇:請求式清除和預約式清除。

  • 請求式清除:當一頁被選擇用於置換時才被寫回到輔存。缺點是寫入一個被修改的頁和讀入一個新頁是成對出現的,並且寫出在讀入之前。相比預約式清除可以減少寫頁,但意味着發生缺頁中斷時,進程在解除阻塞之前必須等待兩次頁傳送,可能降低處理器的利用率。

  • 預約式清除:將這些被修改的多個頁在需要用到它們所佔據的頁框之前被成批的寫回到輔存。缺點是一個被寫回輔存的頁可以仍然留在內存中,指定頁面置換算法指示它被移出。雖然允許成批寫到頁,但可能寫回的頁大部分在置換之前又被修改,因此沒有太大意義。輔存的傳輸能力有限,不應該浪費在實際上不太需要的清除操作上。

        一個比較好的方法是結合頁緩衝技術,只清除可以用於置換的頁,但去除了清除和置換操作之間的成對關係。被置換的頁可以放置在兩個表裏:修改和未修改。修改表的頁可以週期性地被成批寫出,並移到未修改表裏。未修改表的一頁或因爲被訪問而被回收,或它的頁框被分配該另一頁時被淘汰。

加載控制

        影響駐留在內存中的進程數目,稱作爲系統併發度。如果某一時刻進程駐留少,則所有進程同時處於阻塞狀態概率較大,因而有許多時間花費在交互上;如果駐留過多,平均駐留集合大小不夠用,就會頻繁發生缺頁中斷,從而導致抖動。

        隨着系統併發度的增加,剛開始很少出現所以駐留進程都被阻塞的情況,處理器利用率隨着增加;當達到某一點,平均駐留集不夠使用,缺頁率中斷數目迅速增加,出現抖動,從而使處理器利用率下降。

        解決這個問題有多種方法:

  • 工作集或缺頁中斷頻率算法隱含了加載控制,只有駐留集足夠大的進程才允許執行。當爲每個活動進程提供需要的駐留集大小時,該策略自動並且動態的確定了活動進程的數目。

  • L=S準則:調整系統併發度,使缺頁中斷之間的平局時間等於一次缺頁中斷所需要的平均時間,此情況下的處理器的利用率最大。同時有一個類似效果的策略,即將分頁設備的利用率保持在50%,此時的處理器的利用率同樣最大。

  • 時鐘頁面置換算法:使用全局範圍的技術,監視算法中掃描頁框的指針循環緩衝區的速度,如果速度低於某個閾值,則表示有以下一種或兩種情況:很少發生缺頁,因此很少要求指針前進;對每個請求,指針掃描的平局頁框數很小,表示有許多駐留頁每頁被訪問到,並且都易置換。此時系統併發度可以安全的增加。相似的,如果指針掃描速度唱一個最大閾值,則表示缺頁率高,或者難找到可以置換的頁,即表示系統併發度高。

        如果讓系統併發度減少,則要讓一個或多個進程被掛起(換出),其被掛起(換出)的可能性有以下幾種:

  • 最低優先級進程:實現調度策略決策,與性能問題無關。

  • 缺頁中斷進程:有可能是缺頁中斷任務的工作集還沒有駐留,因而掛起它對性能影響最小。此外由於阻塞了一個一定要將被阻塞的進程,並且消除了頁面置換和I/O操作的開銷,所以此選擇可以立即收到成效。

  • 最後一個被激活的進程:這個進程的工作集可能還沒有駐留。

  • 駐留集最小的進程:將來再次轉入時開銷小,但不利於局部性較小的程序。

  • 最大空間的進程:這可以在一個過量使用的內存中得到最多的空閒頁框,使得不會很快又處於去活狀態。

  • 具有最大剩餘執行窗口的進程:一個進程在被中斷或放置在就緒隊列末尾之前只運行一定的時間,類似最短處理時間優先的調度原則。


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