歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux資訊 >> 更多Linux >> Linux核心--4.內存管理

Linux核心--4.內存管理

日期:2017/2/27 14:32:17   编辑:更多Linux
  原著: David A Rusling   翻譯: Banyan & FIFA    第三章 存儲管理     存儲管理子系統時操作系統中最重要的組成部分之一。在早期計算時代,由於人們所需要的內存數目遠遠大於物理內存,人們設計出了各種各樣的策略來解決此問題,其中最成功的是虛擬內存技術。它使得系統中為有限物理內存競爭的進程所需內存空間得到滿足。      虛擬內存技術不僅僅可讓我們可以使用更多的內存,它還提供了以下功能:      巨大的尋址空間      操作系統讓系統看上去有比實際內存大得多的內存空間。虛擬內存可以是系統中實際物理空間的許多倍。每個進程運行在其獨立的虛擬地址空間中。這些虛擬空間相互之間都完全隔離開來,所以進程間不會互相影響。同時,硬件虛擬內存機構可以將內存的某些區域設置成不可寫。這樣可以保護代碼與數據不會受惡意程序的干擾。      內存映射      內存映射技術可以將映象文件和數據文件直接映射到進程的地址空間。在內存映射中,文件的內容被直接連接到進程虛擬地址空間上。      公平的物理內存分配      內存管理子系統允許系統中每個運行的進程公平地共享系統中的物理內存。      共享虛擬內存      盡管虛擬內存允許進程有其獨立的虛擬地址空間,但有時也需要在進程之間共享內存。 例如有可能系統中有幾個進程同時運行BASH命令外殼程序。為了避免在每個進程的虛擬內存空間內都存在BASH程序的拷貝,較好的解決辦法是系統物理內存中只存在一份BASH的拷貝並在多個進程間共享。動態庫則是另外一種進程間共享執行代碼的方式。共享內存可用來作為進程間通訊(IPC)的手段,多個進程通過共享內存來交換信息。 Linux支持SYSTEM V的共享內存IPC機制。      3.1 虛擬內存的抽象模型   在討論Linux是如何具體實現對虛擬內存的支持前,有必要看一下更簡單的抽象模型。      在處理器執行程序時需要將其從內存中讀出再進行指令解碼。在指令解碼之前它必須向內存中某個位置取出或者存入某個值。然後執行此指令並指向程序中下一條指令。在此過程中處理器必須頻繁訪問內存,要麼取指取數,要麼存儲數據。      虛擬內存系統中的所有地址都是虛擬地址而不是物理地址。通過操作系統所維護的一系列表格由處理器實現由虛擬地址到物理地址的轉換。      為了使轉換更加簡單,虛擬內存與物理內存都以頁面來組織。不同系統中頁面的大小可以相同,也可以不同,這樣將帶來管理的不便。Alpha AXP處理器上運行的Linux頁面大小為8KB,而Intel X86系統上使用4KB頁面。每個頁面通過一個叫頁面框號的數字來標示(PFN) 。      頁面模式下的虛擬地址由兩部分構成:頁面框號和頁面內偏移值。如果頁面大小為4KB,則虛擬地址的 11:0位表示虛擬地址偏移值,12位以上表示虛擬頁面框號。處理器處理虛擬地址時必須完成地址分離工作。在頁表的幫助下,它將虛擬頁面框號轉換成物理頁面框號,然後訪問物理頁面中相應偏移處。      圖3.1給出了兩個進程X和Y的虛擬地址空間,它們擁有各自的頁表。這些頁表將各個進程的虛擬頁面映射到內存中的物理頁面。在圖中,進程X的虛擬頁面框號0被映射到了物理頁面框號4。理論上每個頁表入口應包含以下內容:      有效標記,表示此頁表入口是有效的    頁表入口描敘的物理頁面框號    訪問控制信息。用來描敘此頁可以進行哪些操作,是否可寫?是否包含執行代碼?    虛擬頁面框號是為頁表中的偏移。虛擬頁面框號5對應表中的第6個單元(0是第一個)。      為了將虛擬地址轉換為物理地址,處理器首先必須得到虛擬地址頁面框號及頁內偏移。一般將頁面大小設為2的次冪。將圖3.1中的頁面大小設為0x2000字節(十進制為8192)並且在進程Y的虛擬地址空間中某個地址為0x2194,則處理器將其轉換為虛擬頁面框號1及頁內偏移0x194。      處理器使用虛擬頁面框號為索引來訪問處理器頁表,檢索頁表入口。如果在此位置的頁表入口有效,則處理器將從此入口中得到物理頁面框號。如果此入口無效,則意味著處理器存取的是虛擬內存中一個不存在的區域。在這種情況下,處理器是不能進行地址轉換的,它必須將控制傳遞給操作系統來完成這個工作。      某個進程試圖訪問處理器無法進行有效地址轉換的虛擬地址時,處理器如何將控制傳遞到操作系統依賴於具體的處理器。通常的做法是:處理器引發一個頁面失效錯而陷入操作系統核心,這樣操作系統將得到有關無效虛擬地址的信息以及發生頁面錯誤的原因。      再以圖3.1為例,進程Y的虛擬頁面框號1被映射到系統物理頁面框號4,則再物理內存中的起始位置為 0x8000(4 * 0x2000)。加上0x194字節偏移則得到最終的物理地址0x8194。      通過將虛擬地址映射到物理地址,虛擬內存可以以任何順序映射到系統物理頁面。例如,在圖3.1中,進程X的虛擬頁面框號0被映射到物理頁面框號1而虛擬頁面框號7被映射到物理頁面框號0,雖然後者的虛擬頁面框號要高於前者。這樣虛擬內存技術帶來了有趣的結果:虛擬內存中的頁面無須在物理內存保持特定順序。        3.1.1 請求換頁   在物理內存比虛擬內存小得多的系統中,操作系統必須提高物理內存的使用效率。節省物理內存的一種方法是僅加載那些正在被執行程序使用的虛擬頁面。比如說,某個數據庫程序可能要對某個數據庫進行查詢操作,此時並不是數據庫的所有內容都要加載到內存中去,而只加載那些要用的部分。如果此數據庫查詢是一個搜索查詢而無須對數據庫進行添加記錄操作,則加載添加記錄的代碼是毫無意義的。這種僅將要訪問的虛擬頁面載入的技術叫請求換頁。      當進程試圖訪問當前不在內存中的虛擬地址時,處理器在頁表中無法找到所引用地址的入口。在圖3.1中,對於虛擬頁面框號2,進程X的頁表中沒有入口,這樣當進程X試圖訪問虛擬頁面框號2內容時,處理器不能將此地址轉換成物理地址。這時處理器通知操作系統有頁面錯誤發生。      如果發生頁面錯的虛擬地址是無效的,則表明進程在試圖訪問一個不存在的虛擬地址。這可能是應用程序出錯而引起的,例如它試圖對內存進行一個隨機的寫操作。此時操作系統將終止此應用的運行以保護系統中其他進程不受此出錯進程的影響。      如果出錯虛擬地址是有效的,但是它指向的頁面當前不在內存中,則操作系統必須將此頁面從磁盤映象中讀入到內存中來。由於訪盤時間較長,進程必須等待一段時間直到頁面被取出來。如果系統中還存在其他進程,操作系統就會在讀取頁面過程中的等待過程中選擇其中之一來運行。讀取回來的頁面將被放在一個空閒的物理頁面框中,同時此進程的頁表中將添加對應此虛擬頁面框號的入口。最後進程將從發生頁面錯誤的地方重新開始運行。此時整個虛擬內存訪問過程告一段落,處理器又可以繼續進行虛擬地址到物理地址轉換,而進程也得以繼續運行。      Linux使用請求換頁將可執行映象加載到進程的虛擬內存中。當命令執行時,可執行的命令文件被打開,同時其內容被映射到進程的虛擬內存。這些操作是通過修改描敘進程內存映象的數據結構來完成的,此過程稱為內存映射。然而只有映象的起始部分被調入物理內存,其余部分仍然留在磁盤上。當映象執行時,它會產生頁面錯誤,這樣Linux將決定將磁盤上哪些部分調入內存繼續執行。      3.1.2 交換    如果進程需要把一個虛擬頁面調入物理內存而正好系統中沒有空閒的物理頁面,操作系統必須丟棄位於物理內存中的某些頁面來為之騰出空間。     如果那些從物理內存中丟棄出來的頁面來自於磁盤上的可執行文件或者數據文件,並且沒有修改過則不需要保存那些頁面。當進程再次需要此頁面時,直接從可執行文件或者數據文件中讀出。      但是如果頁面被修改過,則操作系統必須保留頁面的內容以備再次訪問。這種頁面被稱為dirty頁面, 當從內存中移出來時,它們必須保存在叫做交換文件的特殊文件中。相對於處理器和物理內存的速度,訪問交換文件的速度是非常緩慢的,操作系統必須在將這些dirty頁面寫入磁盤和將其繼續保留在內存中做出選擇。      選擇丟棄頁面的算法經常需要判斷哪些頁面要丟棄或者交換,如果交換算法效率很低,則會發生"顛簸"現象。在這種情況下,頁面不斷的被寫入磁盤又從磁盤中讀回來,這樣一來操作系統就無法進行其他任何工作。以圖3.1為例,如果物理頁面框號1被頻繁使用,則頁面丟棄算法將其作為交換到硬盤的侯選者是不恰當的。一個進程當前經常使用的頁面集合叫做工作集。高效的交換策略能夠確保所有進程的工作集保存在物理內存中。      Linux使用最近最少使用(LRU)頁面衰老算法來公平地選擇將要從系統中拋棄的頁面。這種策略為系統中的每個頁面設置一個年齡,它隨頁面訪問次數而變化。頁面被訪問的次數越多則頁面年齡越年輕;相反則越衰老。年齡較老的頁面是待交換頁面的最佳侯選者。      3.1.3  共享虛擬內存   虛擬內存讓多個進程之間可以方便地共享內存。所有的內存訪問都是通過每個進程自身的頁表進行。對於兩個共享同一物理頁面的進程,在各自的頁表中必須包含有指向這一物理頁面框號的頁表入口。      圖3.1中兩個進程共享物理頁面框號4。對進程X來說其對應的虛擬頁面框號為4而進程Y的為6。這個有趣的現象說明:共享物理頁面的進程對應此頁面的虛擬內存位置可以不同。      3.1.4  物理與虛擬尋址模式   操作系統自身也運行在虛擬內存中的意義不大。如果操作系統被迫維護自身的頁表那將是一個令人惡心的方案。多數通用處理器




Copyright © Linux教程網 All Rights Reserved