linux全局内存机制和cgroup内存机制

本文详细介绍了Linux内核的内存管理策略,包括匿名页、共享内存和文件页的回收。当内存水位上升时,内核会启动kswapd进行后台回收,而当接近cgroup限制时,会触发直接内存回收,可能导致应用卡顿。在全局内存紧张时,Linux OOM Killer会选择内存使用最多的进程进行杀戮。内存回收策略对系统性能有显著影响,特别是在内存超卖场景下,可能导致性能抖动。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 内存页的分类

linux进程使用的内存页面(page)的主要分类:
1)匿名页:来自堆、栈、数据段,需要换出到交换区 (swap-out)来回收(reclaim)。
2)共享内存:来自匿名 mmap 映射、shmem 共享内存,需要换出到交换区(swap-out)来回收(reclaim)。
3)文件页:来自代码段、文件映射,需要通过页面换出(page-out)来回收(reclaim),如果释放的是脏页则需要回写磁盘,因为必须让内存数据和磁盘数据保持一致。


2 cgroup级的内存直接回收(不存在后台回收)

Linux内核的原则是尽可能地使用内存(贪婪使用),直接内存回收这个工作主要发生在内存水位比较高的时候。
当容器自身的所有内存用量(包含 page cache)接近 cgroup limit 时,会触发 cgrou级别的直接内存回收(direct reclaim)来回收干净的文件页,这个内存回收过程发生在进程申请内存的上下文,此时线程不是在做自身业务而是在执行内核代码回收内存,因此会造成应用的卡顿。
此时,如果内存申请速率超出回收速率,Linux OOM Killer 将对cgroup中的所有进程进行大到小排序,杀死使用内存最多的进程来释放内存。


3 全局内存后台回收和直接回收

当整机内存资源紧张时,进程申请内存会有机会触发后台回收文件页和直接回收文件页。图片来自极客时间。
在这里插入图片描述

1)当空闲内存开始低于watermark low水位线(vm.min_free_kbytes)时,唤醒内核线程kswapd回收page cache,不会阻塞应用进程运行,支持对脏页的回收,kswapd线程会持续回收内存直到内存水位达到于watermark high。图片来自极客时间。
在这里插入图片描述

2)当空闲内存开始低于Min水位线时(Min < Low),会触发全局的直接内存回收,该过程发生在进程分配内存的上下文,且期间需要扫描更多页面、回写脏页,节点上所有任务都可能被干扰。图片来自极客时间。
在这里插入图片描述

3)当整机的内存分配速率超出回收速率时,则会触发整机的OOM,linux oom killer找出整机中内存使用量最大的进程进行强制杀死以释放内存。

4)全局的直接内存回收对系统性能有很大影响,例如在内存超卖场景中,资源消耗型任务会时常瞬间申请大量的内存,使得整机的空闲内存开始低于全局最低水位线(global wmark_min),引发整机上所有任务进入直接内存回收的慢速路径,进而导致延敏感型业务的性能抖动,这是一件不公平的事情,内存未超卖的进程(usage < request )被内存超卖的进程(usage > request )拖累了。

### 修改 Linux 系统中的最大物理内存限制 在 Linux 中,可以通过控制组(Cgroups)来管理资源分配,其中包括设置内存限制。以下是关于如何通过 Cgroups 来实现对特定进程或容器的最大物理内存限制的方法。 #### 使用 Cgroups 设置 Memory Limit Cgroups 提供了一种机制用于限制、记录隔离一组进程所使用的资源。要设置某个 cgroup内存上限,可以按照以下方式操作: 1. **创建一个新的 cgroup** 首先需要创建一个新目录以表示新的 cgroup 控制组。 ```bash sudo mkdir /sys/fs/cgroup/memory/my_group ``` 2. **挂载 memory 子系统到该路径** 如果尚未挂载 `memory` 子系统,则需手动完成此步骤。 ```bash sudo mount -t cgroup -o memory none /sys/fs/cgroup/memory/ ``` 3. **设定内存限制** 编辑 `/sys/fs/cgroup/memory/my_group/memory.limit_in_bytes` 文件并写入期望的字节数值。例如,如果希望将内存限制为 512MB: ```bash echo $((512 * 1024 * 1024)) | sudo tee /sys/fs/cgroup/memory/my_group/memory.limit_in_bytes ``` 这里的 `$(( ))` 是一种算术表达式的简化形式[^1]。 4. **附加进程至指定 cgroup** 将目标进程 ID 添加到对应的 tasks 列表中。 ```bash echo <PID> | sudo tee /sys/fs/cgroup/memory/my_group/tasks ``` #### 调整全局系统的内存限制 除了针对单个 cgroup 或者容器外,在某些情况下可能也需要调整整个系统的可用物理内存大小。这种需求通常较少见于生产环境,但在测试或者调试场景下可能会被用到。 - 对于虚拟机而言,可以直接减少分配给 VM 的 RAM 数量; - 物理服务器上则可通过 GRUB 参数临时降低硬件可识别的总容量。具体做法如下所示: 1. 编辑引导加载程序配置文件 (通常是 `/boot/grub/grub.cfg`) 并加入 kernel 启动选项 `mem=XXXM` ,其中 XXX 表示想要保留的实际 MB 值。 ```bash mem=8G ``` 2. 更新 grub 配置使其生效,并重启机器应用变更。 ```bash sudo update-grub && sudo reboot now ``` 上述过程描述了两种不同的方法分别适用于局部与整体层面下的内存管控策略[^3]。 ```python def set_memory_limit(group_name, limit_mb): import os path = f"/sys/fs/cgroup/memory/{group_name}" if not os.path.exists(path): os.makedirs(path) with open(f"{path}/memory.limit_in_bytes", "w") as file: file.write(str(limit_mb * 1024 * 1024)) set_memory_limit('test', 512) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值