內存是計算機系統最重要的資源之一,當操作系統內存不足時,進程申請內存將會失敗,從而導致其運行異常或者崩潰。
Linux 內核提供swap機制來解決內存不足的情況,其原理是:
當系統內存不足時,內核會將進程不常用的內存交換(寫入)到磁盤中,然后將這些內存歸還給系統,系統可以將這些內存繼續分配給其他需要使用內存的進程。
通過 swap 機制,系統可以將內存分配給需求更迫切的進程。但由于 swap 機制需要進行 I/O 操作,所以一定程度上會影響系統性能。那么是否存在一種能夠節省內存,而且對性能影響較少的機制呢?
在 Linux-3.14 引入了一種名為zRAM的技術,zRAM 的原理是:將進程不常用的內存壓縮存儲,從而達到節省內存的使用。如下圖所示:

zRAM 機制建立在 swap 機制之上,swap 機制是將進程不常用的內存交換到磁盤中,而 zRAM 機制是將進程不常用的內存壓縮存儲在內存某個區域。所以 zRAM 機制并不會發生 I/O 操作,從而避免因 I/O 操作導致的性能下降。
zRAM原理
由于 zRAM 機制是建立在 swap 機制之上,而 swap 機制需要配置文件系統或塊設備來完成的。所以 zRAM 虛擬一個塊設備,當系統內存不足時,swap 機制將內存寫入到這個虛擬的塊設備中。也就是說,zRAM 機制本質上只是一個虛擬塊設備。
zRAM 的原理如下圖所示:

從上圖可以看出,在開啟了 zRAM 機制的情況下,當系統內存不足時,內核會進行如下操作:
通過 swap 機制從系統中查找一些進程不常用的內存。
將這些不常用的內存交換到 zRAM 塊設備中,而 zRAM 塊設備首先會對這些不常用的內存進行壓縮,然后存儲起來。
把不常用的內存壓縮存儲到 zRAM 塊設備后,swap 機制會把這些不常用的內存歸還給內核。
當進程訪問到這些被交換到 zRAM 塊設備的內存時,swap 機制將會通過 zRAM 塊設備解壓這些內存,并且重新建立與進程的地址映射關系。
啟用zRAM
1. 創建 zRAM 塊設備
要啟用 zRAM,首先需要創建 zRAM 塊設備。要創建 zRAM 塊設備,可以使用以下命令:
modprobezramnum_devices=1
num_devices參數可以指定創建 zRAM 塊設備的個數,上面命令創建了一個 zRAM 塊設備,可以通過路徑/dev/zram0來訪問這個塊設備。
2. 設置 zRAM 塊設備的大小
創建完 zRAM 塊設備后,可以通過以下命令來設置其空間大小:
echo512M>/sys/block/zram0/disksize
上面命令設置了zram0的大小為 512MB,也就是說,zram0能夠存儲 512MB 壓縮后的數據。
3. 壓縮算法選擇
zRAM 機制支持多種壓縮算法,不同的壓縮算法有不同的壓縮比率和壓縮速度,用戶可以按照自身的需求來選擇不同的壓縮算法。
要更改 zRAM 的壓縮算法,可以使用下面命令:
echolzo>/sys/block/zram0/comp_algorithm
上面命令將 zRAM 的壓縮算法更改為lzo,我們也可以通過下面命令來查看內核支持哪些壓縮算法:
cat/sys/block/zram0/comp_algorithm lzo[lz4]
從上面命令的輸出可知,內核支持lzo和lz4兩種壓縮算法。
4. 將 swap 交換設備設置為 zRAM
要將 swap 的交換設備設置為 zRAM 塊設備,可以使用以下命令:
mkswap/dev/zram0
當執行完上面這條命令后,內核將會使用zram0作為 swap 的交換設備。
zRAM實現
zRAM 塊設備驅動的實現代碼主要在drivers/block/zram/zram_drv.c文件中,下面我們主要圍繞此文件進行分析。
本文并不會介紹塊設備驅動的編寫流程,只會分析 swap 機制在進行內存交換時,與 zRAM 塊設備驅動的交互。
壓縮內存
當系統內存不足時,內核將會觸發swap機制。swap 機制首先會從系統中選擇一些進程不常用內存,然后將這些不常用的內存交換到zRAM塊設備中(使用 zRAM 塊設備作為交換設備的情況下)。
當 swap 機制將不常用的內存交換到 zRAM 塊設備時,會調用zram_make_request()函數處理請求。而zram_make_request()最終會通過調用zram_bvec_write()函數來壓縮內存,調用鏈如下:
zram_make_request() ->__zram_make_request() ->zram_bvec_rw() ->zram_bvec_write()
我們來分析一下zram_bvec_write()函數的實現,其代碼如下:
staticint
zram_bvec_write(structzram*zram,structbio_vec*bvec,u32index,intoffset)
{
...
//1.獲取需要進行壓縮的內存
page=bvec->bv_page;
...
user_mem=kmap_atomic(page);
uncmem=user_mem;
...
//2.對內存進行壓縮
ret=zcomp_compress(zram->comp,zstrm,uncmem,&clen);
...
//3.獲取壓縮后的數據
src=zstrm->buffer;
...
//4.申請一個內存塊保存壓縮后的數據
handle=zs_malloc(meta->mem_pool,clen);
...
cmem=zs_map_object(meta->mem_pool,handle,ZS_MM_WO);
//5.將壓縮后的數據保存到新申請的內存塊中
memcpy(cmem,src,clen);
...
//6.將壓縮后的數據登記到zRAM塊設備的表格中
meta->table[index].handle=handle;
...
returnret;
}
為了簡化分析過程,我們對代碼進行精簡。從上面的代碼可以看出,zRAM 機制對內存進行壓縮的步驟如下:
獲取需要進行壓縮的內存,需要進行壓縮的內存由 swap 機制提供。
通過zcomp_compress()函數對內存進行壓縮,src指針指向壓縮后的內存地址。
通過zs_malloc()和zs_map_object()函數申請一塊新的內存塊,大小為壓縮后數據的大小。
將壓縮后的數據復制到新申請的內存塊中。
將壓縮后的數據記錄到zRAM塊設備的表格中。
由于 zRAM 塊設備是建立在內存中的虛擬塊設備,所以其并沒有真實塊設備的特性。真實塊設備會將存儲空間劃分成一個個塊,而zram_bvec_write()函數的index參數就是數據塊的編號。此參數有 swap 機制提供,所以 zRAM 塊設備驅動通過 index 參數作為原始內存數據的編號。
一圖勝千言:

zRAM驅動有個數據塊表,用來記錄原始內存數據對應的壓縮數據,此表的索引就是數據塊的編號。swap 機制會維護此表格的使用情況,如哪個塊是空閑的,哪個塊被占用等。
當內存頁被壓縮后,swap 機制將會把原來的內存頁釋放掉,并且把所有映射到此內存頁的進程解除映射,細節可以參考 swap 機制相關的資料。
審核編輯:劉清
-
Linux系統
+關注
關注
4文章
614瀏覽量
29902 -
SWAP
+關注
關注
0文章
52瀏覽量
13678 -
zram
+關注
關注
0文章
3瀏覽量
138
原文標題:一文讀懂|zRAM 內存壓縮機制
文章出處:【微信號:LinuxHub,微信公眾號:Linux愛好者】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
什么是制冷壓縮機,制冷壓縮機的工作原理
肖特推出了電動壓縮機標準的壓縮機端子系列產品
半導體制冷和壓縮機制冷哪個好
多滑片式壓縮機結構圖_多滑片式壓縮機的特點
制冷壓縮機的種類_制冷壓縮機的結構
zRAM內存壓縮機制詳解
評論