一文读懂|zRAM 内存压缩机制

news2024/11/23 10:46:12

内存是计算机系统最重要的资源之一,当操作系统内存不足时,进程申请内存将会失败,从而导致其运行异常或者崩溃。

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 块设备,可以使用以下命令:

modprobe zram num_devices=1

num_devices 参数可以指定创建 zRAM 块设备的个数,上面命令创建了一个 zRAM 块设备,可以通过路径 /dev/zram0 来访问这个块设备。

2. 设置 zRAM 块设备的大小

创建完 zRAM 块设备后,可以通过以下命令来设置其空间大小:

echo 512M > /sys/block/zram0/disksize

上面命令设置了 zram0 的大小为 512MB,也就是说, zram0 能够存储 512MB 压缩后的数据。

3. 压缩算法选择

zRAM 机制支持多种压缩算法,不同的压缩算法有不同的压缩比率和压缩速度,用户可以按照自身的需求来选择不同的压缩算法。

要更改 zRAM 的压缩算法,可以使用下面命令:

echo lzo > /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 的交换设备。

 资料直通车:Linux内核源码技术学习路线+视频教程内核源码

学习直通车:Linuxc/c++高级开发【直播公开课】

零声白金VIP体验卡:零声白金VIP体验卡(含基础架构/高性能存储/golang/QT/音视频/Linux内核)

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() 函数的实现,其代码如下:

static int
zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, int offset)
{
    ...
    // 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;
    ...
    return ret;
}

为了简化分析过程,我们对代码进行精简。从上面的代码可以看出,zRAM 机制对内存进行压缩的步骤如下:

  • 获取需要进行压缩的内存,需要进行压缩的内存由 swap 机制提供。
  • 通过 zcomp_compress() 函数对内存进行压缩,src 指针指向压缩后的内存地址。
  • 通过 zs_malloc() 和 zs_map_object() 函数申请一块新的内存块,大小为压缩后数据的大小。
  • 将压缩后的数据复制到新申请的内存块中。
  • 将压缩后的数据记录到 zRAM 块设备的表格中。

由于 zRAM 块设备是建立在内存中的虚拟块设备,所以其并没有真实块设备的特性。真实块设备会将存储空间划分成一个个块,而 zram_bvec_write() 函数的 index 参数就是数据块的编号。此参数有 swap 机制提供,所以 zRAM 块设备驱动通过 index 参数作为原始内存数据的编号。

一图胜千言:

zRAM驱动有个数据块表,用来记录原始内存数据对应的压缩数据,此表的索引就是数据块的编号。swap 机制会维护此表格的使用情况,如哪个块是空闲的,哪个块被占用等。

当内存页被压缩后,swap 机制将会把原来的内存页释放掉,并且把所有映射到此内存页的进程解除映射,细节可以参考 swap 机制相关的资料。

对内存进行解压缩的过程与压缩过程相反,有兴趣的同学可以自行阅读代码,这里就不进行分析了。

原文作者:Linux内核那些事

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1069503.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

线性数据—栈、队列、链表

一、栈 Stack(存取O(1)) 先进后出,进去123,出来321。 基于数组:最后一位为栈尾,用于取操作。 基于链表:第一位为栈尾,用于取操作。 1.1、数组栈 /*** 基于数组实现的顺序栈&#…

记录:Unity脚本的编写2.0

目录 前言控制方法键盘控制鼠标控制虚拟控制器控制 平移和旋转 前言 前面记录了一些简单的unity脚本用来控制unity中对象模型的移动(或者不能叫控制,毕竟它是开启之后自己在跑的),那么让模型可以根据用户的操作来进行变化的方法自…

SQL监控工具

什么是 SQL 监控 SQL 监视是跟踪和分析整个 MSSQL 生态系统的过程,以识别性能问题并防止依赖数据库的应用程序变慢和/或遇到中断,它有助于获取有关 SQL 服务器的数据库会话、查询、作业、CPU 和内存资源、群集、配置和可用性组的信息。 为什么 MSSQL 监…

JavaScript 笔记: 函数

1 函数声明 2 函数表达式 2.1 函数表达式作为property的value 3 箭头函数 4 构造函数创建函数(不推荐) 5 function 与object 5.1 typeof 5.2 object的操作也适用于function 5.3 区别于⼀般object的⼀个核⼼特征 6 回调函数 callback 7 利用function的pr…

TensorFlow入门(十、共享变量)

使用tf.Variable方法创建变量 使用tf.Variable方法创建变量时有两点需要注意: ①一般情况下,使用tf.Variable方法创建的变量都有作用域,也可叫做变量的可用性范围,即在变量所属的模型内,变量的名字是有效可用的。 ②使用tf.Variable方法创建变量时,会生成一个新的变量。如果在一…

激活函数与loss的梯度

激活函数: 最开始由生物学家对青蛙的神经元机制进行研究发现,青蛙的神经元有多个输入x0、x1、x2,响应值是他们加权后的结果,但响应值如果小于阈值,则不会响应,而只有大于阈值时,才会有固定的响应…

LeetCode 1277. 统计全为 1 的正方形子矩阵【动态规划】1613

本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章…

紫光 DDR3 IP核调试

1. IP核简介 直接编写DDR2/DDR3的逻辑工作量不太大,但是涉及到双边延、高速率的读取,时序很复杂。因此一般抖采用IP核实现。紫光的SDRAM IP核为HMIC_H IP。 HMIC_H IP 包括了 DDR Controller、DDR PHY 和 PLL,用户通过 AXI4 接口实现数据的读…

十三、MySQL 主从复制

一、MySQL 主从复制 1. 主从复制原理 主库 有一个 工作线程 I/O dump thread(转储线程)。从库 有两个工作线程 I/O thread 和 SQL thread。主库 通过 I/O dump thread 给 从库 I/O thread 传送 binlog 日志。 主从同步过程中: 主库 把接收的…

大厂笔试真题【栈】美团2023春招-火车迷【欧弟算法】全网最全大厂秋招题解

文章目录 题目描述与示例题目描述输入描述输出描述示例一输入输出 示例二输入输出 解题思路代码pythonJavaC时空复杂度 华为OD算法/大厂面试高频题算法练习冲刺训练 题目描述与示例 题目描述 小美是一个火车迷。最近她在观察家附近火车站的火车驶入和驶出情况,发现…

C/C++学习 -- Base64算法

Base64算法概述 Base64是一种用于将二进制数据表示为ASCII字符集中的可打印字符的编码方法。它由64个不同的字符组成,通常包括26个大写字母、26个小写字母、10个数字以及两个特殊字符(通常是""和"/")。Base64编码的目的…

【Vue基础-数字大屏】地图标记涟漪效果设置

一、需求说明 将地图中北京市、陕西市、南宁市分别以实心圆、涟漪圆、涟漪圆标记出来 二、代码实践 涉及三个文件 1、App.vue: <template><Screen1/> </template> <script> import Screen1 from "./components/Screen1.vue"; export def…

如何应对数据安全四大挑战?亚马逊云科技打出“组合拳”

数字经济时代&#xff0c;数据被公认为继土地、劳动力、资本、 技术之后的又一重要生产要素。对于企业而言&#xff0c;数据则是一切创新与关键决策的根源。 然而&#xff0c;企业在发挥数据资产的商业价值方面&#xff0c;却面临诸多挑战&#xff0c;比如敏感数据识别、跨组织…

【高阶数据结构】图详解第一篇:图的基本概念及其存储结构(邻接矩阵和邻接表)

文章目录 1. 图的基本概念1.1 什么是图1.2 有向图和无向图1.3 完全图1.4 邻接顶点1.5 顶点的度1.6 路径1.7 路径长度1.8 简单路径与回路1.9 子图1.10 连通图1.11 强连通图1.12 生成树 2. 图的存储结构2.1 邻接矩阵2.2 邻接矩阵代码实现结构定义构造函数添加边打印图测试 2.3 邻…

leetCode 718.最长重复子数组 动态规划 + 优化(滚动数组)

718. 最长重复子数组 - 力扣&#xff08;LeetCode&#xff09; 给两个整数数组 nums1 和 nums2 &#xff0c;返回 两个数组中 公共的 、长度最长的子数组的长度 。 示例 1&#xff1a; 输入&#xff1a;nums1 [1,2,3,2,1], nums2 [3,2,1,4,7] 输出&#xff1a;3 解释&…

2023年台州市第三届网络安全技能大赛(MISC)这是神马

这是神马 考点&#xff1a;冰蝎流量特征数据包&#xff0c;需要解密 emoj解密 冰蝎之前做过 特征就是先base64编码在AES编码 我们在数据包里面找到了密钥&#xff1a;144a6b2296333602 这里我们知道了密钥我们就去解密 先筛选HTTP协议 导出HTTP数据流可以看到传了shell.php 随…

美容美甲小程序商城的作用是什么

美容院往往有很高需求&#xff0c;女性悦己经济崛起&#xff0c;加之爱美化程度提升&#xff0c;无论线下环境还是线上互联网信息冲击&#xff0c;美容服务、化妆产品等市场规格一直稳增不减。 通过【雨科】平台制作美容美甲商城&#xff0c;售卖相关服务/产品&#xff0c;模块…

记两次内网入侵溯源

1.1、入侵告警 1、某天深夜主机防护突然爆出CS木马后门&#xff0c;这攻击队不讲武德呀&#xff0c;还好没睡着2、赶紧叫醒旁边看流量设备的哥们儿&#xff0c;尝试Shiro 反序列漏洞攻击成功3、测试目标网站存在shiro反序列化漏洞1.2、上机排查 1、上机将CS木马下载下来&…

Vue3 reactive和ref详解

reactive Vue3.0中的reactive reactive 是 Vue3 中提供的实现响应式数据的方法。在 Vue2 中响应式数据是通过 defineProperty 来实现的&#xff0c;在 Vue3 中响应式数据是通过 ES6 的 Proxy来实现的。reactive 参数必须是对象 (json / arr)如果给 reactive 传递了其它对象 默…

基于JavaWeb的家用电器信息管理系统

本系统采用基于JAVA语言实现、架构模式选择B/S架构&#xff0c;Tomcat7.0及以上作为运行服务器支持&#xff0c;基于JAVA等主要技术和框架设计&#xff0c;idea作为开发环境&#xff0c;数据库采用MYSQL5.7以上。 开发环境&#xff1a; JDK版本&#xff1a;JDK1.8 服务器&…