作業系統之十 記憶體分頁管理與swap

2022-07-30 16:42:13 字數 4607 閱讀 4949

一、虛擬記憶體

電腦裡記憶體分記憶體條(這裡我們叫物理記憶體)和硬碟,記憶體條儲存程式執行時資料,硬碟持久儲存資料。那麼虛擬記憶體是什麼?

程式執行會啟動乙個程序,程序裡有程式段、全域性資料、棧和堆,這些都會載入到記憶體裡,每一部分都有對應的記憶體位址,程序就是一直在處理這些位址中資料。

然而在linux下,程序不能直接讀寫記憶體位址。

程序中能訪問的位址,只能是虛擬記憶體位址(virtual memory address)。

作業系統會把虛擬記憶體位址翻譯成真實的記憶體位址。

這種記憶體管理方式,稱為虛擬記憶體(virtual memory)。

特點1、虛擬記憶體位址和物理記憶體位址類似,都是為資料提供位置索引;

2、虛擬記憶體位址和物理記憶體位址通過對映關係來關聯;

3、不同程序都有自己的一套虛擬記憶體位址,用來給自己的程序空間編號;

4、程序的虛擬記憶體位址相互獨立。因此,兩個程序空間可以有相同的虛擬記憶體位址,如0x10001000。

5、應用程式的資料讀寫操作的是虛擬位址,對物理記憶體位址一無所知。

6、程式中表達的記憶體位址,也都是虛擬記憶體位址。

7、程序對虛擬記憶體位址的操作,會被作業系統翻譯成對某個物理記憶體位址的操作。

優勢:1、借助虛擬記憶體位址,作業系統可以保障程序空間的獨立性,不同程序就不可能相互篡改對方的資料,程序出錯的可能性就大為減少。

2、有了虛擬記憶體位址,記憶體共享也變得簡單。作業系統可以把同一物理記憶體區域對應到多個程序空間。這樣,不需要任何的資料複製,多個程序就可以看到相同的資料。核心和共享庫的對映,就是通過這種方式進行的.

二、記憶體分頁

通過上面對虛擬記憶體的介紹得知,作業系統必須能高效地翻譯虛擬記憶體和物理記憶體位址對映。

linux採用了分頁(paging)的方式來記錄對應關係。

所謂的分頁,就是以更大尺寸的單位頁(page)來管理記憶體。

記憶體分頁,可以極大地減少所要記錄的記憶體對應關係。我們已經看到,以位元組為單位的對應記錄實在太多。如果把物理記憶體和程序空間的位址都分成頁,核心只需要記錄頁的對應關係,相關的工作量就會大為減少。

在linux中,通常每頁大小為4kb。

使用命令檢視記憶體頁大小:

多級分頁表

單一的連續分頁表,需要給每乙個虛擬頁預留一條記錄的位置。但對於任何乙個應用程序,其程序空間真正用到的位址都相當有限。我們還記得,程序空間會有棧和堆。程序空間為棧和堆的增長預留了位址,但棧和堆很少會佔滿程序空間。這意味著,如果使用連續分頁表,很多條目都沒有真正用到。因此,linux中的分頁表,採用了多層的資料結構。多層的分頁表能夠充分利用記憶體空間。

三、swap

1、swap是什麼?

swap字面意思是交換,指硬碟上一塊分割槽或者檔案。

在linux上可以使用swapon -s命令檢視當前系統上正在使用的交換空間清單:

[root@pcs101 ~]# swapon -s

filename type size used priority

/dev/dm-1 partition 16777208

0 -1

2、swap作用

當物理記憶體(記憶體條)不夠用的時候,將部分記憶體上的資料交換到swap空間上,以便讓系統不會因記憶體不夠用而導致oom或者更致命的情況出現。

當某程序向os請求記憶體發現不足時,os會把記憶體中暫時不用的資料交換出去,放在swap分割槽中,這個過程稱為swap out。

當某程序又需要這些資料且os發現還有空閒物理記憶體時,又會把swap分割槽中的資料交換回物理記憶體中,這個過程稱為swap in。

3、記憶體**

使用swap是記憶體**機制一項實現方式。

3.1核心進行記憶體**的主要原因有兩個:

(1)核心需要為任何時刻突發到來的記憶體申請提供足夠的記憶體,所以一般情況下保證有足夠的free空間對於核心來說是必要的。

(2)linux核心使用cache的策略雖然是不用白不用,核心會使用記憶體中的page cache對部分檔案進行快取,以便提公升檔案的讀寫效率。所以核心有必要設計乙個週期性**記憶體的機制,以便cache的使用和其他相關記憶體的使用不至於讓系統的剩餘記憶體長期處於很少的狀態。

3.2兩種記憶體**機制:

(1)使用kswapd程序對記憶體進行週期檢查,以保證平常狀態下剩餘記憶體盡可能夠用;

(2)直接記憶體**(directpagereclaim),就是當記憶體分配時沒有空閒記憶體可以滿足要求時,觸發直接記憶體**。

3.3記憶體**會對兩種記憶體的使用進行**:

(1)匿名記憶體,這部分記憶體沒有實際載體,不像檔案快取有硬碟檔案這樣乙個載體,比如典型的堆、棧資料等。這部分內存在**的時候不能直接釋放或者寫回類似檔案的媒介中,這才搞出來swap這個機制,將這類記憶體換出到硬碟中,需要的時候再載入出來。

(2)檔案快取,為了避免檔案資料每次都要從硬碟讀取,系統會將熱點資料儲存在記憶體中,提高效能。如果僅僅將檔案讀出來,記憶體**只需要釋放這部分記憶體即可,下次再次讀取該檔案資料直接從硬碟中讀取即可(類似hbase檔案快取)。那如果不僅將檔案讀出來,而且對這些快取的檔案資料進行了修改(髒資料),**記憶體就需要將這部分資料檔案寫會硬碟再釋放(類似mysql檔案快取)。

603.5、記憶體**策略引數:zone_reclaim_mode這個引數定義了numa架構下不同的記憶體**策略,

echo 0 > /proc/sys/vm/zone_reclaim_mode:在local記憶體不夠用的情況下可以去其他的記憶體區域分配記憶體;

echo 1 > /proc/sys/vm/zone_reclaim_mode:表示開啟zone_reclaim模式,在local記憶體不夠用的情況下本地先**再分配;

echo 2 > /proc/sys/vm/zone_reclaim_mode:本地**盡可能先**檔案快取物件;在本地**記憶體時,可以將cache中的髒資料寫回硬碟,以**記憶體。

echo 4 > /proc/sys/vm/zone_reclaim_mode:可以用swap方式**記憶體。

3.6 kswapd週期檢查和記憶體標記水位線

linux核心使用水位標記(watermark)的概念來描述記憶體壓力情況,三種記憶體水位標記:high、low、min

(1)剩餘內存在high以上表示記憶體剩餘較多,目前記憶體使用壓力不大;

(2)high-low的範圍表示目前剩餘記憶體存在一定壓力;

(3)low-min表示記憶體開始有較大使用壓力,剩餘記憶體不多了;

(4)min是最小的水位標記,當剩餘記憶體達到這個狀態時,就說明記憶體面臨很大壓力。

(5)小於min這部分記憶體,核心是保留給特定情況下使用的,一般不會分配。

所有的記憶體watermark標記都是根據當前記憶體總大小和乙個可調引數進行運算得來的,這個引數是:/proc/sys/vm/min_free_kbytes

記憶體**行為就是基於剩餘記憶體的水位標記進行決策的:

當系統剩餘記憶體低於watermark[low]的時候,核心的kswapd開始起作用,進行記憶體**。直到剩餘記憶體達到watermark[high]的時候停止。

如果記憶體消耗導致剩餘記憶體達到了或超過了watermark[min]時,就會觸發直接**(direct reclaim)。

4、swap優先順序

在使用多個swap分割槽或者檔案的時候,還有乙個優先順序的概念(priority)。

在swapon的時候,我們可以使用-p引數指定相關swap空間的優先順序,值越大優先順序越高,可以指定的數字範圍是-1到32767。

核心在使用swap空間的時候總是先使用優先順序高的空間,後使用優先順序低的。

5、資料庫系統討厭swap

swap機制的初衷是為了緩解物理記憶體用盡而選擇直接粗暴oom程序的尷尬。但幾乎所有資料庫對swap都不怎麼待見,無論mysql、oracal、mongodb抑或hbase,為什麼?

(1)資料庫系統一般都對響應延遲比較敏感,如果使用swap代替記憶體,資料庫服務效能必然不可接受。對於響應延遲極其敏感的系統來講,延遲太大和服務不可用沒有任何區別,比服務不可用更嚴重的是,swap場景下程序就是不死,這就意味著系統一直不可用……再想想如果不使用swap直接oom,是不是一種更好的選擇,這樣很多高可用系統直接會主從切換掉,使用者基本無感知。

(2)對於諸如hbase這類分布式系統來說,其實並不擔心某個節點宕掉,而恰恰擔心某個節點夯住。乙個節點宕掉,最多就是小部分請求短暫不可用,重試即可恢復。但是乙個節點夯住會將所有分布式請求都夯住,伺服器端執行緒資源被占用不放,導致整個集群請求阻塞,甚至集群被拖垮。

參考:linux的記憶體分頁管理

linux記憶體管理swap分割槽

linux swap的那些事

linux swap詳解

linux swap分割槽

作業系統 記憶體的分頁管理與分段管理 異同

比較點 分頁分段 目的頁是資訊的物理單位 分頁是為了實現離散分配方式,以抵消記憶體的外部碎片,提高記憶體利用率 分頁僅僅是由於系統管理的需要而不是使用者的需要 段是資訊的邏輯單位 分段是為了能更好地滿足使用者的需要 長度頁的長度固定且由系統決定,由系統把邏輯位址劃分為頁號和頁內位址兩部分,這是由機器...

作業系統 記憶體管理與記憶體分割槽

主要是以下幾點,做以了解 重定位 由於記憶體是被多程序共享的。那麼在在某個程式執行期間,誰也不知道會有其他那些程式駐留在記憶體中。所以,有時會將那些暫不需要的程序換出記憶體。恢復時,如果要恢復到切換之前的同一記憶體位址會非常困難,所以就要將程序進行重定位到記憶體的不同區域。保護 每個程序都應該收到保...

作業系統之記憶體分割槽與分頁

如何將程式中的 段 資料段等內容存放在記憶體中?1 採用可變分割槽的方法,每次存放程式段之前找到與之大小匹配的空閒記憶體段,然後存放進去。2 採用此種方法需要維護2個核心資料表 空閒分割槽表和已分配分割槽表。3 此種方法隨著程序段的增多會造成大量的小空閒分割槽,也叫作記憶體碎片。如果不加以處理,會降...