linux物理内存虚拟内存一致,Liunx内存管理的调用和实现
下面我們探討一下關于內存管理的系統調用方式。事實上,POSIX 并沒有給內存管理指定任何的系統調用。然而,Linux 卻有自己的內存系統調用,主要系統調用如下
系統調用描述s = brk(addr)改變數據段大小a = mmap(addr,len,prot,flags,fd,offset)進行映射s = unmap(addr,len)取消映射
如果遇到錯誤,那么 s 的返回值是 -1,a 和 addr 是內存地址,len 表示的是長度,prot 表示的是控制保護位,flags 是其他標志位,fd 是文件描述符,offset 是文件偏移量。
brk 通過給出超過數據段之外的第一個字節地址來指定數據段的大小。如果新的值要比原來的大,那么數據區會變得越來越大,反之會越來越小。
mmap 和 unmap 系統調用會控制映射文件。mmp 的第一個參數 addr 決定了文件映射的地址。它必須是頁面大小的倍數。如果參數是 0,系統會分配地址并返回 a。第二個參數是長度,它告訴了需要映射多少字節。它也是頁面大小的倍數。prot 決定了映射文件的保護位,保護位可以標記為「可讀、可寫、可執行或者這些的結合」。第四個參數 flags 能夠控制文件是私有的還是可讀的以及 addr 是必須的還是只是進行提示。第五個參數 fd 是要映射的文件描述符。只有打開的文件是可以被映射的,因此如果想要進行文件映射,必須打開文件;最后一個參數 offset 會指示文件從什么時候開始,并不一定每次都要從零開始。
Linux 內存管理實現
內存管理系統是操作系統最重要的部分之一。從計算機早期開始,我們實際使用的內存都要比系統中實際存在的內存多。內存分配策略克服了這一限制,并且其中最有名的就是 虛擬內存(virtual memory)。通過在多個競爭的進程之間共享虛擬內存,虛擬內存得以讓系統有更多的內存。虛擬內存子系統主要包括下面這些概念。
「大地址空間」
操作系統使系統使用起來好像比實際的物理內存要大很多,那是因為虛擬內存要比物理內存大很多倍。
「保護」
系統中的每個進程都會有自己的虛擬地址空間。這些虛擬地址空間彼此完全分開,因此運行一個應用程序的進程不會影響另一個。并且,硬件虛擬內存機制允許內存保護關鍵內存區域。
「內存映射」
內存映射用來向進程地址空間映射圖像和數據文件。在內存映射中,文件的內容直接映射到進程的虛擬空間中。
「公平的物理內存分配」
內存管理子系統允許系統中的每個正在運行的進程公平分配系統的物理內存。
「共享虛擬內存」
盡管虛擬內存讓進程有自己的內存空間,但是有的時候你是需要共享內存的。例如幾個進程同時在 shell 中運行,這會涉及到 IPC 的進程間通信問題,這個時候你需要的是共享內存來進行信息傳遞而不是通過拷貝每個進程的副本獨立運行。
下面我們就正式探討一下什么是 虛擬內存
虛擬內存的抽象模型
在考慮 Linux 用于支持虛擬內存的方法之前,考慮一個不會被太多細節困擾的抽象模型是很有用的。
處理器在執行指令時,會從內存中讀取指令并將其解碼(decode),在指令解碼時會獲取某個位置的內容并將他存到內存中。然后處理器繼續執行下一條指令。這樣,處理器總是在訪問存儲器以獲取指令和存儲數據。
在虛擬內存系統中,所有的地址空間都是虛擬的而不是物理的。但是實際存儲和提取指令的是物理地址,所以需要讓處理器根據操作系統維護的一張表將虛擬地址轉換為物理地址。
為了簡單的完成轉換,虛擬地址和物理地址會被分為固定大小的塊,稱為 頁(page)。這些頁有相同大小,如果頁面大小不一樣的話,那么操作系統將很難管理。Alpha AXP系統上的 Linux 使用 8 KB 頁面,而 Intel x86 系統上的 Linux 使用 4 KB 頁面。每個頁面都有一個唯一的編號,即頁面框架號(PFN)。
上面就是 Linux 內存映射模型了,在這個頁模型中,虛擬地址由兩部分組成:「偏移量和虛擬頁框號」。每次處理器遇到虛擬地址時都會提取偏移量和虛擬頁框號。處理器必須將虛擬頁框號轉換為物理頁號,然后以正確的偏移量的位置訪問物理頁。
上圖中展示了兩個進程 A 和 B 的虛擬地址空間,每個進程都有自己的頁表。這些頁表將進程中的虛擬頁映射到內存中的物理頁中。頁表中每一項均包含
有效標志(valid flag):表明此頁表條目是否有效該條目描述的物理頁框號訪問控制信息,頁面使用方式,是否可寫以及是否可以執行代碼
要將處理器的虛擬地址映射為內存的物理地址,首先需要計算虛擬地址的頁框號和偏移量。頁面大小為 2 的次冪,可以通過移位完成操作。
如果當前進程嘗試訪問虛擬地址,但是訪問不到的話,這種情況稱為 缺頁異常,此時虛擬操作系統的錯誤地址和頁面錯誤的原因將通知操作系統。
通過以這種方式將虛擬地址映射到物理地址,虛擬內存可以以任何順序映射到系統的物理頁面。
按需分頁
由于物理內存要比虛擬內存少很多,因此操作系統需要注意盡量避免直接使用低效的物理內存。節省物理內存的一種方式是僅加載執行程序當前使用的頁面(這何嘗不是一種懶加載的思想呢?)。例如,可以運行數據庫來查詢數據庫,在這種情況下,不是所有的數據都裝入內存,只裝載需要檢查的數據。這種僅僅在需要時才將虛擬頁面加載進內中的技術稱為按需分頁。
交換
如果某個進程需要將虛擬頁面傳入內存,但是此時沒有可用的物理頁面,那么操作系統必須丟棄物理內存中的另一個頁面來為該頁面騰出空間。
如果頁面已經修改過,那么操作系統必須保留該頁面的內容,以便以后可以訪問它。這種類型的頁面被稱為臟頁,當將其從內存中移除時,它會保存在稱為交換文件的特殊文件中。相對于處理器和物理內存的速度,對交換文件的訪問非常慢,并且操作系統需要兼顧將頁面寫到磁盤的以及將它們保留在內存中以便再次使用。
Linux 使用最近最少使用(LRU)頁面老化技術來公平的選擇可能會從系統中刪除的頁面,這個方案涉及系統中的每個頁面,頁面的年齡隨著訪問次數的變化而變化,如果某個頁面訪問次數多,那么該頁就表示越 年輕,如果某個呃頁面訪問次數太少,那么該頁越容易被換出。
物理和虛擬尋址模式
大多數多功能處理器都支持 物理地址模式和虛擬地址模式的概念。物理尋址模式不需要頁表,并且處理器不會在此模式下嘗試執行任何地址轉換。Linux 內核被鏈接在物理地址空間中運行。
Alpha AXP 處理器沒有物理尋址模式。相反,它將內存空間劃分為幾個區域,并將其中兩個指定為物理映射的地址。此內核地址空間稱為 KSEG 地址空間,它包含從 0xfffffc0000000000 向上的所有地址。為了從 KSEG 中鏈接的代碼(按照定義,內核代碼)執行或訪問其中的數據,該代碼必須在內核模式下執行。鏈接到 Alpha 上的 Linux內核以從地址 0xfffffc0000310000 執行。
訪問控制
頁面表的每一項還包含訪問控制信息,訪問控制信息主要檢查進程是否應該訪問內存。
必要時需要對內存進行訪問限制。例如包含可執行代碼的內存,自然是只讀內存;操作系統不應允許進程通過其可執行代碼寫入數據。相比之下,包含數據的頁面可以被寫入,但是嘗試執行該內存的指令將失敗。大多數處理器至少具有兩種執行模式:內核態和用戶態。你不希望訪問用戶執行內核代碼或內核數據結構,除非處理器以內核模式運行。
訪問控制信息被保存在上面的 Page Table Entry ,頁表項中,上面這幅圖是 Alpha AXP的 PTE。位字段具有以下含義
V
表示 valid ,是否有效位
FOR
讀取時故障,在嘗試讀取此頁面時出現故障
FOW
寫入時錯誤,在嘗試寫入時發生錯誤
FOE
執行時發生錯誤,在嘗試執行此頁面中的指令時,處理器都會報告頁面錯誤并將控制權傳遞給操作系統,
ASM
地址空間匹配,當操作系統希望清除轉換緩沖區中的某些條目時,將使用此選項。
GH
當在使用單個轉換緩沖區條目而不是多個轉換緩沖區條目映射整個塊時使用的提示。
KRE
內核模式運行下的代碼可以讀取頁面
URE
用戶模式下的代碼可以讀取頁面
KWE
以內核模式運行的代碼可以寫入頁面
UWE
以用戶模式運行的代碼可以寫入頁面
頁框號
對于設置了 V 位的 PTE,此字段包含此 PTE 的物理頁面幀號(頁面幀號)。對于無效的 PTE,如果此字段不為零,則包含有關頁面在交換文件中的位置的信息。
除此之外,Linux 還使用了兩個位
_PAGE_DIRTY
如果已設置,則需要將頁面寫出到交換文件中
_PAGE_ACCESSED
Linux 用來將頁面標記為已訪問。
緩存
上面的虛擬內存抽象模型可以用來實施,但是效率不會太高。操作系統和處理器設計人員都嘗試提高性能。但是除了提高處理器,內存等的速度之外,最好的方法就是維護有用信息和數據的高速緩存,從而使某些操作更快。在 Linux 中,使用很多和內存管理有關的緩沖區,使用緩沖區來提高效率。
緩沖區緩存
緩沖區高速緩存包含塊設備驅動程序使用的數據緩沖區。
還記得什么是塊設備么?這里回顧下
塊設備是一個能存儲固定大小塊信息的設備,它支持「以固定大小的塊,扇區或群集讀取和(可選)寫入數據」。每個塊都有自己的物理地址。通常塊的大小在 512 - 65536 之間。所有傳輸的信息都會以連續的塊為單位。塊設備的基本特征是每個塊都較為對立,能夠獨立的進行讀寫。常見的塊設備有「硬盤、藍光光盤、USB 盤」
與字符設備相比,塊設備通常需要較少的引腳。
緩沖區高速緩存通過設備標識符和塊編號用于快速查找數據塊。如果可以在緩沖區高速緩存中找到數據,則無需從物理塊設備中讀取數據,這種訪問方式要快得多。
頁緩存
頁緩存用于加快對磁盤上圖像和數據的訪問
它用于一次一頁地緩存文件中的內容,并且可以通過文件和文件中的偏移量進行訪問。當頁面從磁盤讀入內存時,它們被緩存在頁面緩存中。
交換區緩存
僅僅已修改(臟頁)被保存在交換文件中
只要這些頁面在寫入交換文件后沒有修改,則下次交換該頁面時,無需將其寫入交換文件,因為該頁面已在交換文件中。可以直接丟棄。在大量交換的系統中,這節省了許多不必要的和昂貴的磁盤操作。
硬件緩存
處理器中通常使用一種硬件緩存。頁表條目的緩存。在這種情況下,處理器并不總是直接讀取頁表,而是根據需要緩存頁的翻譯。這些是轉換后備緩沖區 也被稱為 TLB,包含來自系統中一個或多個進程的頁表項的緩存副本。
引用虛擬地址后,處理器將嘗試查找匹配的 TLB 條目。如果找到,則可以將虛擬地址直接轉換為物理地址,并對數據執行正確的操作。如果處理器找不到匹配的 TLB 條目, 它通過向操作系統發信號通知已發生 TLB 丟失獲得操作系統的支持和幫助。系統特定的機制用于將該異常傳遞給可以修復問題的操作系統代碼。操作系統為地址映射生成一個新的 TLB 條目。清除異常后,處理器將再次嘗試轉換虛擬地址。這次能夠執行成功。
使用緩存也存在缺點,為了節省精力,Linux 必須使用更多的時間和空間來維護這些緩存,并且如果緩存損壞,系統將會崩潰。
總結
以上是生活随笔為你收集整理的linux物理内存虚拟内存一致,Liunx内存管理的调用和实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么删除win10文件夹权限不足 如何解
- 下一篇: linux服务器 32核,Intel换成