IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 什么是overcommit_memory? -> 正文阅读

[系统运维]什么是overcommit_memory?

1. 前言

在日常的工作中可能我们会经常遇到程序fork失败的问题。遇到fork失败往往有两种可能性:

  1. 进程数超标:可以通过cat /proc/sys/kernel/threads-max查看
  2. 内存不足

进程数预设值往往很大,几乎不太能超标,所以fork失败的原因大部分都是由于内存不足造成的。

我们知道,由于MMU实现了虚拟地址到物理地址的转换,所以我们在申请虚拟地址时往往可以申请一大块内存,这实际上是对资源的有效利用,毕竟只有内存真正被投入使用时(如memset)才会实际分配物理内存,这种允许内存超额commit的机制就是overcommit_memory。

虚拟内存需要物理内存作为支撑,当分配了太多虚拟内存,导致物理内存不够时,就发生了Out Of Memory。这种允许超额commit的机制就是overcommit

其调用链关系如下图所示。
在这里插入图片描述

从图中我们可以看到,fork一步一步执行到了__vm_enough_memory,该接口是overcommit的核心。

2. 原理

Linux根据参数vm.overcommit_memory设置overcommit:

  • 0 ——默认值,启发式overcommit,它允许overcommit,但太明显的overcommit会被拒绝,比如malloc一次性申请的内存大小就超过了系统总内存。
  • 1 ——Always overcommit. 允许overcommit,对内存申请来者不拒。
  • 2 ——不允许overcommit,提交给系统的总地址空间大小不允许超过。

include/uapi/linux/mman.h中声明了该宏定义:

#define OVERCOMMIT_GUESS		0
#define OVERCOMMIT_ALWAYS		1
#define OVERCOMMIT_NEVER		2

sysctl_overcommit_memory等于OVERCOMMIT_ALWAYS时,内核的处理方式是直接返回。

if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS)
		return 0;

sysctl_overcommit_memory等于OVERCOMMIT_GUESS,主要代码如下:

if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) {
		free = global_page_state(NR_FREE_PAGES);
		free += global_node_page_state(NR_FILE_PAGES);
		free -= global_node_page_state(NR_SHMEM);
		free += get_nr_swap_pages();
		free += global_page_state(NR_SLAB_RECLAIMABLE);

		if (free <= totalreserve_pages)
			goto error;
		else
			free -= totalreserve_pages;
    
		if (!cap_sys_admin)
			free -= sysctl_admin_reserve_kbytes >> (PAGE_SHIFT - 10); /* 为root保留的页数 */

		if (free > pages)
			return 0;

		goto error;
}

其中global_page_state负责读取vm_zone_stat数组中的各项值。

extern atomic_long_t vm_zone_stat[NR_VM_ZONE_STAT_ITEMS];
  • NR_FREE_PAGES:富足的未分配资源;
  • NR_FILE_PAGES:page cache总和;
  • NR_SHMEM:进程间的share memory;
  • NR_SLAB_RECLAIMABLE:slab可回收的页数;
  • totalreserve_pages:每个zone保留的不能被用户空间分配的页数;
  • get_nr_swap_pages:针对空闲的swap页数

所以free的计算公式如下:

free = NR_FREE_PAGES + NR_FILE_PAGES - NR_SHMEM + swap_pages + NR_SLAB_RECLAIMABLE

如果此时free小于totalreserve_pages,则判定内存不足,否则 free -= totalreserve_pages.

如果是普通进程,则还需要保留admin_reserve_kbytes(/proc/sys/vm/admin_reserve_kbytes)的free page.

此时free若大于申请的pages,则不会发生overcommit。


sysctl_overcommit_memory等于OVERCOMMIT_NEVER,相关代码如下:

allowed = vm_commit_limit();

	if (!cap_sys_admin)
		allowed -= sysctl_admin_reserve_kbytes >> (PAGE_SHIFT - 10);

	if (mm) {
		reserve = sysctl_user_reserve_kbytes >> (PAGE_SHIFT - 10);
		allowed -= min_t(long, mm->total_vm / 32, reserve);
	}

	if (percpu_counter_read_positive(&vm_committed_as) < allowed)
		return 0;
error:
	vm_unacct_memory(pages);

	return -ENOMEM;

/
unsigned long vm_commit_limit(void)
{
	unsigned long allowed;

	if (sysctl_overcommit_kbytes)
		allowed = sysctl_overcommit_kbytes >> (PAGE_SHIFT - 10);
	else
		allowed = ((totalram_pages - hugetlb_total_pages())
			   * sysctl_overcommit_ratio / 100);
	allowed += total_swap_pages;

	return allowed;
}  

主要看如下值:

  • sysctl_overcommit_kbytes:/proc/sys/vm/overcommit_kbytes的值
  • sysctl_overcommit_ratio:/proc/sys/vm/overcommit_ratio的值
  • totalram_pages:可分配的总页数
  • total_swap_pages:可换出的页数
  • hugetlb_total_pages:huge page相关
  • sysctl_user_reserve_kbytes:/proc/sys/vm/user_reserve_kbytes的值,用户空间保留的内存大小
  • vm_committed_as:保存了当前系统中已经申请的虚拟内存大小

由代码可知,vm_commit_limit包括两种情况:

  1. 如果overcommit_kbytes不为0, allow值为overcommit_kbytes的一半;
  2. 如果overcommit_kbytes为0,allow值为可管理的总内存与vercommit_ratio的乘积百分比

3. 设置

那么如何设置overcommit的值呢?有三种方法:

  1. 编辑**/etc/sysctl.conf** ,改vm.overcommit_memory=1,然后sysctl -p使配置文件生效
  2. sysctl vm.overcommit_memory=1
  3. echo 1 > /proc/sys/vm/overcommit_memory

4. 总结

本文通过分析内核代码粗略得分析了overcommit_memory的原理,也为后面的OOM-killer的原理做个铺垫。

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-01-24 11:21:19  更:2022-01-24 11:23:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 20:21:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码