本文讨論的 swap基于Linux4.4内核代碼 。Linux内存管理是一套非常複雜的系統,而swap隻是其中一個很小的處理邏輯。主要是:swap、swappiness及kswapd原理,swap分區優先級的妙用。
解決以下問題:
1、 swap到底是幹嘛的?
2、 什麼是内存水位标記?
3、 swap分區的優先級(prIOrity)有啥用?
我們一般所說的swap,指的是一個交換分區或文件。在Linux上可以使用swapon -s命令查看當前系統上正在使用的交換空間有哪些,以及相關信息:
$ swapon -s filename Type Size Used Priority /dev/dm-4 partition 33554428 0 -1
從功能上講,交換分區主要是在内存不夠用的時候,将部分内存上的數據交換到swap空間上,以便讓系統不會因内存不夠用而導緻oom或者更緻命的情況出現。
所以,當内存使用存在壓力,開始觸發内存回收的行為時,就可能會使用swap空間。
内核對swap的使用實際上是跟内存回收行為緊密結合的。那麼關于内存回收和swap的關系,我們需要思考以下幾個問題:
下面我們就從這些問題出發,一個一個進行分析。
為什麼要進行内存回收?
根據這個enum可以看到,内存回收主要需要進行掃描的鍊表有如下4個:
就是說,内存回收操作主要針對的就是内存中的文件頁(file cache)和匿名頁。
關于活躍(active)還是不活躍(inactive)的判斷内核會使用lru算法進行處理并進行标記,我們這裡不詳細解釋這個過程。
整個掃描的過程分幾個循環:
4.進行swap的時候,先對inactive的頁進行換出;
5.如果是file的文件映射page頁,則判斷其是否為髒數據,如果是髒數據就寫回,不是髒數據可以直接釋放。
這樣看來, 内存回收這個行為會對兩種内存的使用進行回收:
因為針對filebased的内存,沒必要進行交換,其數據原本就在硬盤上,回收這部分内存隻要在有髒數據時寫回,并清空内存就可以了,以後有需要再從對應的文件讀回來。
内存對匿名頁和文件緩存一共用了 四條鍊表 進行組織,回收過程主要是針對這四條鍊表進行掃描和操作。
那麼如何描述内存使用的壓力呢?
Linux内核使用水位标記(watermark)的概念來描述這個壓力情況。
Linux為内存的使用設置了三種内存水位标記:high、low、min。他們 所标記的含義分别為:
内存回收行為就是基于剩餘内存的水位标記進行決策的:
當系統剩餘内存低于watermark[low]的時候,内核的kswapd開始起作用,進行内存回收。直到剩餘内存達到watermark[high]的時候停止。
如果内存消耗導緻剩餘内存達到了或超過了watermark[min]時,就會觸發直接回收(direct reclaim)。
明白了水位标記的概念之後,zonefile zonefree <= high_wmark_pages(zone)這個公式就能理解了。
這裡的zonefile相當于内存中文件映射的總量,zonefree相當于剩餘内存的總量。
内核一般認為,如果zonefile還有的話,就可以盡量通過清空文件緩存獲得部分内存,而不必隻使用swap方式對anon的内存進行交換。
整個判斷的概念是說,在全局回收的狀态下(有global_reclaim(sc)标記),如果當前的文件映射内存總量 剩餘内存總量的值評估小于等于watermark[high]标記的時候,就可以進行直接swap了。
這樣是為了防止進入cache陷阱,具體描述可以見代碼注釋。
這個判斷對系統的影響是, swappiness設置為0時,有剩餘内存的情況下也可能發生交換。
swap的相關操縱命令
可以使用mkswap将一個分區或者文件創建成swap空間。swapon可以查看當前的swap空間和啟用一個swap分區或者文件。swapoff可以關閉swap空間。
我們使用一個文件的例子來演示一下整個操作過程:
制作swap文件:
啟用swap文件:
關閉swap空間:
在使用多個swap分區或者文件的時候,還有一個優先級的概念(Priority)。
在swapon的時候,我們可以使用-p參數指定相關swap空間的優先級, 值越大優先級越高 ,可以指定的數字範圍是-1到32767。
内核在使用swap空間的時候總是先使用優先級高的空間,後使用優先級低的。
當然如果把多個swap空間的優先級設置成一樣的,那麼兩個swap空間将會以輪詢方式并行進行使用。
如果兩個swap放在兩個不同的硬盤上,相同的優先級可以起到類似RAID0的效果,增大swap的讀寫效率。
另外,編程時使用mlock()也可以将指定的内存标記為不會換出,具體幫助可以參考man 2 mlock。
關于swap的使用建議,針對不同負載狀态的系統是不一樣的。有時我們希望swap大一些,可以在内存不夠用的時候不至于觸發oom-killer導緻某些關鍵進程被殺掉,比如數據庫業務。
也有時候我們希望不要swap,因為當大量進程爆發增長導緻内存爆掉之後,會因為swap導緻IO跑死,整個系統都卡住,無法登錄,無法處理。
這時候我們就希望不要swap,即使出現oom-killer也造成不了太大影響,但是不能允許服務器因為IO卡死像多米諾骨牌一樣全部死機,而且無法登陸。跑cpu運算的無狀态的apache就是類似這樣的進程池架構的程序。
覺得有用的關注下哦~
,
更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!