Linux - 内存、swap、内存回收机制

news2024/11/13 10:31:18

参考

2023年6月22日

  • https://zhuanlan.zhihu.com/p/107350459 —— 讨论的swap基于Linux4.4内核代码
  • 内存深度科普: 从堆内存到虚拟内存管理

2023年6月22日 qbittorrent swap 问题

  • https://github.com/qbittorrent/qBittorrent/issues/12947 massif valgrind --tool=massif qbittorrent
    • https://github.com/qbittorrent/qBittorrent/issues/12326#issuecomment-606296172 MTTuner
  • https://github.com/qbittorrent/qBittorrent/issues/11372

正文

内存

进程内存、用户系统空间(User Space Address)、系统虚拟内存(Virtual Memory)、物理内存(Physical Memory)

程序内存 ⇒ 物理内存

  • 在linux中,程序以进程形式运行,使用的内存称为“进程内存” —— 使用
  • “进程内存”由“用户系统空间”提供 —— 资源分配、权限管理
  • “用户系统空间”由“系统虚拟内存”提供 —— 系统管理(封装硬件调用,暴露调用接口)
  • “虚拟内存”通过“内存分页”映射到“物理内存”上 —— 物理to逻辑

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

读文件

处理器直接与内存交互、不直接与硬盘交互

如果内存没预先加载想要的硬盘数据,进程会进入中断,等待硬盘数据写入内存

程序逻辑地址、内存虚拟地址、硬盘物理地址

在这里插入图片描述

进程内存

进程(progress)内存(memory)使用有两种数据结构

  • Stack(栈) —— 大小已知的小资源
    • 方法调用
    • 本地变量存储
  • Heap(堆) —— 大小可变的大资源
    • 对象存储
    • callocmallocreallocfree —— 生成/释放一定大小的“块数据(block)”

在这里插入图片描述

在“进程”的内存空间中,堆和栈的内存空间相对生长。如果两者吃满,就会导致内存用尽,抛出OOM异常,进程终止。

在这里插入图片描述
在这里插入图片描述

所以,c语言的手动内存管理(manual heap allocation)写起来麻烦,写错了更麻烦。因此,在c以后的语言或多或少用“对象(Object)”、“类(Class)”的抽象概念替代堆、栈的具体概念,有意避免下游的开发者进行手动的堆栈内存管理,然后在语言编码层面封装了内存管理流程。
在这里插入图片描述
在这里插入图片描述

当然,这种自动管理内存的模式带来的弊端是“更多的程序执行步骤”,也就是(相对)更低的程序性能。
为了提高程序性能,如希望加快Android应用的响应速度,而Java部分无法再优化时,基于C/C++开发的NDK就会被选择 —— 开发者手动管理内存。

在这里插入图片描述

swap

Linux内存管理是一套非常复杂的系统,而swap只是其中一个很小的处理逻辑。

作用

  1. 内存扩展 —— “交换分区(swap)”主要是在内存不够用的时候,将部分内存上的数据交换到swap空间上,以便让系统不会因内存不够用而导致oom或者更致命的情况出现。
  2. 内存回收 —— 当进程不再需要某些内存数据时,这些将死、无用的进程的数据可以移动到swap分区中,从而释放物理内存空间。
  3. 系统休眠、恢复 —— 当系统需要休眠时,可以将内存中的数据保存在swap分区中,以便在唤醒后可以恢复到之前的状态。

swap分区一般设置为物理内存的1.5~2倍。
实际上,更具体的考虑,应该考虑实际的物理内存大小,实际的运行程序,硬盘类型来决定swap分区大小
e.g.

  • 小内存,大swap。大内存,swap不重要,但至少要是物理内存的一倍
  • nginx吃内存小、tomcat吃内存多、文件服务器 内存决定响应速度
  • 物理硬盘,往小了设置swap分区,确保程序不oom即可。

查看(挂载)

# see MOUNTPOINT
lsblk

查看(运行时)

查看个大概

$ htop

在这里插入图片描述

查看具体数值

$ free
              total        used        free      shared  buff/cache   available
Mem:        3856724     2281072      168644        1492     1407008     1315044
Swap:       4411308     1415572     2995736

查看分区

$ swapon -s
Filename                                Type            Size    Used    Priority
/dev/md1                                partition       2097084 63360   -1
/dev/zram0                              partition       578556  334768  1
/dev/zram1                              partition       578556  335844  1
/dev/zram2                              partition       578556  334904  1
/dev/zram3                              partition       578556  335864  1

创建(文件形式)

dd if=/dev/zero of=/swapfile bs=1G count=16
chmod 0600 /swapfile
格式化
mkswap /swapfile
# 挂载
swapon /swapfile
# 验证
free -h

创建(分区形式)

mkswap /dev/sdb4
swapon /dev/sdb4
free -h

swap策略

Linux有一个内核参数vm.swappiness,取值0-100,0表示不想用swap、100表示非常想用swap

e.g. pc,16g,swappiness=60,大约在6G(16G*40%=6.4G)的内存时候开始使用swap

$ cat /proc/sys/vm/swappiness
60
$ sysctl vm.swappiness # 查看
vm.swappiness = 60
$ vm.swappiness = 60 # 临时调整
$ echo 10 > /proc/sys/vm/swappiness # 临时调整
$ cat /etc/sysctl.conf | grep swap
vm.swappiness=10
$ sysctl -p # 激活

内存回收机制

内核(kernel)进行内存回收,原因主要有两个

  1. 内核需要为突发时刻到来的“内存申请”提供足够的“内存”,所以一般情况下需要保证有足够的free空间。
    当真的有大于空闲内存的申请到来的时候,会触发强制内存回收。
  2. 内核会使用内存中的page cache对部分文件进行缓存,以便提升文件的读写效率。
    但文件读写是随机的,所以可能大部分page cache长期不会被触发。
    所以内核有要设计一个周期性回收内存的机制,避免内存被长期占用。

所以,内核在应对这两类回收的需求下,分别实现了两种不同的机制

  1. 一个是使用kswapd进程对内存进行周期检查,以保证平常状态下剩余内存尽可能够用。
  2. 一个是直接内存回收(direct page reclaim),就是当内存分配时没有空闲内存可以满足要求时,触发直接内存回收

这两种内存回收的触发路径不同:

  1. 一个是由内核进程kswapd直接调用内存回收的逻辑进行内存回收;
    参见mm/vmscan.c中的kswapd()主逻辑
  2. 一个是内存申请的时候进入slow path的内存申请逻辑进行回收。
    参见内核代码中的mm/page_alloc.c中的__alloc_pages_slowpath方法

内存回收的方法、针对的对象

内存回收的两个过程在实际进行时殊途同归,最终都是调用shrink_zone()方法进行针对每个zone的内存页缩减。

这个方法中会再调用shrink_lruvec()(LRU,least recently used,最近最少使用)这个方法对每个"组织页"的链表进程检查。

这些链表主要定义在mm/vmscan.c一个enum中:

在这里插入图片描述

找到这个线索之后,我们就可以清晰的看到内存回收操作究竟针对的page有哪些了。

根据这个enum可以看到,内存回收主要需要进行扫描的链表有如下4个:

  • anoninactive
  • anonactive
  • fileinactive
  • fileactive

就是说,内存回收操作主要针对的就是内存中的文件页(file cache)和匿名页。

内存标记、内存回收流程

整个扫描的过程分几个循环:

  1. 首先扫描每个zone上的cgroup组;
  2. 然后再以cgroup的内存为单元进行page链表的扫描;
  3. 内核会先扫描anonactive链表(LRU_ACTIVE_ANON),将不频繁的放进inactive链表中(LRU_INACTIVE_ANON),然后扫描inactive链表,将里面活跃的移回active中;
    在这里插入图片描述

    关于活跃(active)还是不活跃(inactive)的判断内核会使用lru算法进行处理并进行标记,我们这里不详细解释这个过程。

  4. 进行swap的时候,先对inactive的页进行换出;
  5. 如果是file的文件映射page页(LRU_INACTIVE_FILE),则判断其是否为脏数据,如果是脏数据就写回,不是脏数据可以直接释放。

    脏数据:写入内存后,未同步

这样看来,内存回收这个行为会对两种内存的使用进行回收:

一种是anon的匿名页内存,主要回收手段是swap;

另一种是file-backed的文件映射页,主要的释放手段是写回和清空。

todo https://mp.weixin.qq.com/s?__biz=MzA4Nzg5Nzc5OA==&mid=2651660097&idx=1&sn=a3d38e3af2c9d8d431c46fe7680b428d&scene=2&srcid=0606f21oK1jm1IKMwEyi6aNz&from=timeline&isappinstalled=0#wechat_redirect

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

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

相关文章

taro实现小程序地图打点

使用taro的map标签&#xff0c;往markers里放入点位&#xff1a; <map v-if"mapLoading" id"mapId":longitude"userPosition.x":latitude"userPosition.y":show-location"false":markers"markerList":scale&q…

Spring Boot 如何使用 JUL 进行日志记录

Spring Boot 如何使用 JUL 进行日志记录 在 Spring Boot 中&#xff0c;我们可以使用多种日志框架进行日志记录。其中&#xff0c;JUL (Java Util Logging) 是 Java 平台自带的日志框架&#xff0c;它提供了简单的 API 和配置&#xff0c;可以轻松地进行日志记录。本文将介绍如…

RocketMQ 常见面试题(一)

RocketMQ Broker 中的消息被消费后会立即删除吗&#xff1f; 不会&#xff0c;每条消息都会持久化到 CommitLog 中&#xff0c;每个 Consumer 连接到 Broker 后会维持消费进度信息&#xff0c;当有消息消费后只是当前Consumer 的消费进度&#xff08;CommitLog 的 offset&…

【计算机视觉】在计算机视觉里,传统卷积已经彻底输给Transformer了吗?

文章目录 一、传统卷积 & Transformer1.1 传统卷积1.2 Transformer 二、知乎高赞回答2.1 作者&#xff1a;知乎用户2.2 作者&#xff1a;王云鹤2.3 作者&#xff1a;知乎用户 一、传统卷积 & Transformer 1.1 传统卷积 传统卷积&#xff08;Traditional Convolution&…

【初识C语言(3)】选择语句+循环语句+函数+数组

文章目录 1. 选择语句2. 循环语句3. 函数4. 数组 C语言是一门结构化的程序设计语言 顺序结构&#xff1b; 选择结构&#xff1b; 循环结构。 1. 选择语句 生活中处处面临着选择&#xff0c;如果你好好学习&#xff0c;校招时拿一个好offer&#xff0c;走上人生巅峰。如果你不学…

案例突破——悲观锁和乐观锁

悲观锁和乐观锁 一、背景介绍二、悲观锁和乐观锁什么是悲观锁什么是乐观锁 三、 在项目中如何使用悲观锁和乐观锁在项目中使用悲观锁实体结构实体对象的xml配置文件对应生成的表结构往表中初始化数据运行之后的结果模拟触发悲观锁的条件核心代码 在项目中使用乐观锁实体结构(添…

【探索 Kubernetes|作业管理 Deployment 篇 系列 12】水平扩展 / 收缩、滚动 / 回滚更新

前言 大家好&#xff0c;我是秋意零。 在上一篇中&#xff0c;我们介绍了控制器的基本设计思想&#xff1a;控制器模式。通过这个 “控制器模式” 我们来看看 Deployment 是如何依靠它来实现的。 最近搞了一个扣扣群&#xff0c;旨在技术交流、博客互助&#xff0c;希望各位…

第40步 深度学习图像识别:DenseNet201建模(Tensorflow)

基于WIN10的64位系统演示 一、写在前面 &#xff08;1&#xff09;DenseNet201 DenseNet201是一种深度卷积神经网络&#xff0c;是DenseNet网络的一种变体。DenseNet&#xff0c;全称Dense Convolutional Network&#xff08;密集卷积网络&#xff09;&#xff0c;是由Faceb…

【VC 7/8】vCenter Server 更新(小版本升级)Ⅱ—— 使用 Shell 命令行更新 vCenter Server

目录 2. 使用 Shell 升级 vCenter Server&#xff08;1&#xff09;下载更新 ISO 镜像&#xff08;2&#xff09;挂载 ISO 镜像&#xff08;3&#xff09;验证 ISO 镜像已被挂载通过VAMI 更新界面将ISO 挂载到 VC 的文件系统 &#xff08;4&#xff09;更新 VC | 安装 vCenter …

Elasticsearch:如何通过 3 个简单步骤从 Elastic 数据中删除个人身份信息

作者&#xff1a;Peter Titov 对于任何组织来说&#xff0c;个人身份信息 (Personally Identifiable information, PII) 合规性都是一个日益严峻的挑战。 无论你是在电子商务、银行、医疗保健还是其他数据敏感的领域&#xff0c;PII 都可能会在无意中被捕获和存储。 拥有结构化…

丰田汽车投资人要求董事长下台

&#x1f699; 丰田电动车推广不力&#xff0c;股东要求董事长下台 Toyota faced down two proxy votes at its annual general meeting. In an unusual challenge to the management of a Japanese company, activist investors in America and Europe recommended voting aga…

跨境电商产品的评价怎么获取?

对于在亚马逊、沃尔玛、eBay、Wish、Newegg、速卖通、阿里国际站、Shopee、Lazada、Temu、乐天、Toktok、Joom、Ozon等跨境电商平台的卖家来说&#xff0c;产品评价和补单&#xff08;增加订单数&#xff09;是一个常见但至关重要的话题 优质的产品评价可以向潜在买家展示我们…

想学习大数据,主要学什么?

什么是大数据 什么是“大数据”呢&#xff1f;如果从字面意思来看&#xff0c;大数据指的是巨量数据。那么可能有人会问&#xff0c;多大量级的数据才叫大数据&#xff1f;不同的机构或学者有不同的理解&#xff0c;难以有一个非常定量的定义&#xff0c;只能说&#xff0c;大…

【技术干货】高精度室内定位方案,影响UWB定位精度的因素分析

物联网时代&#xff0c;室内定位已然成为物联网建设的技术纽带&#xff0c;想要真正发挥位置数据的价值&#xff0c;就需要采集的位置数据有足够精度。基于UWB技术的厘米级UWB高精度室内定位方案已广泛应用于物联网各行业领域的人员定位及资产管理。本篇小编就来带大家了解一下…

QGIS 3D功能操作说明

QGIS可以轻松快速地创建 3D 地图和可视化。可用于3d数据效果浏览及与2D数据的对比及数据的打印输出。具体功能如下。 1.在 QGIS 中&#xff0c;您可以通过几个简单的步骤创建 3D 模型。 (1)在QGIS中添加3D 数据的数据层&#xff0c;例如DEM&#xff0c;以供3D功能使用。 …

快速下载操作系统镜像文件-ubuntu-centos

一键搞定镜像文件下载 操作方式 链接地址&#xff1a;阿里云镜像文件链接地址 点击【OS镜像】弹框中选择相应版本 弹框中选择好相应的发行版本后点击【下载】即可

将数组内的元素变为指定格式的字符串类型numpy.char.mod()方法

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 将数组内的每个元素 修改为指定格式的字符串 numpy.char.mod() [太阳]选择题 关于以下代码说法错误的一项是? import numpy as np a np.array([1, 2, 3]) print("【显示】a ",a) p…

前端Vue自定义导航栏菜单 定制左侧导航菜单按钮 中部logo图标 右侧导航菜单按钮

前端Vue自定义导航栏菜单 定制左侧导航菜单按钮 中部logo图标 右侧导航菜单按钮&#xff0c; 下载完整代码请访问uni-app插件市场地址&#xff1a;https://ext.dcloud.net.cn/plugin?id13152 效果图如下&#xff1a; # cc-navHeader #### 使用方法 使用方法 在page.json设…

轻量级的深度学习框架Tinygrad

Tinygrad是一个轻量级的深度学习库&#xff0c;它提供了一种简化和直观的方法来理解和实现神经网络。在本文中&#xff0c;我们将探讨Tinygrad及其主要功能&#xff0c;以及它如何成为那些开始深度学习之旅的人的有价值的工具。 什么是Tinygrad? Tinygrad是一个开源的深度学习…

Redis持久化机制介绍

Redis持久化 1.Redis持久化2.Redis 的持久化机制是什么&#xff1f;各自的优缺点&#xff1f;2.1.RDB&#xff1a;是Redis DataBase缩写快照2.2.AOF&#xff1a;持久化2.3.AOF和RDB优缺点是什么&#xff1f; 3. 如何选择合适的持久化方式4.Redis持久化数据和缓存怎么做扩容&…