当前位置: 首页 > news >正文

Linux Mem -- 通过reserved-memory缩减内存

目录

1. reserved-memory缩减内存

2. 为什么要通过2段512GB预留内存实现该缩减呢?

3. reserved-momery中的no-map属性

4. 预留的的内存是否会被统计到系统MemTotal中?


 

本文是解决具体的一些思考总结,和Linux内核的reserved-memory机制相关。

参考代码:Linux-6.10

1. reserved-memory缩减内存

        实际开发过程有需求验小内存产品时系统性能情况,为节省成本直接将大内存产品的内存进行软件缩减成小内然后进行性能验证。

        例如有8GB内存产品需要缩减为7GB内存,通过Linux内核的reserved-memory机制实现该缩减需求,具体修改如下。通过预留2段512GB内存的reserved-memory内存,来达到缩减1GB内存的目的。对于此预留机制实现的缩减方案会有一些疑问,随后就相关疑问进行调查解答。

reserved-memory {
		#address-cells = <2>;
		#size-cells = <2>;
		ranges;

		removed-memory1:removed_memory_region1 {
			alloc-renges=<0x0 0x00000000 0xffffffff 0xffffffff>;
			size= <0x0 0x20000000>; //512MBytes
			no-map;
		};
		
		removed-memory2:removed_memory_region2 {
			alloc-renges=<0x0 0x00000000 0xffffffff 0xffffffff>;
			size= <0x0 0x20000000>; //512MBytes
			no-map;
		};
		
}

2. 为什么要通过2段512GB预留内存实现该缩减呢?

        答案是可以是1段1GB或者多个段合成1GB遗留内存,但是要确保每段的预留内存可以预留成功。

        reserved-momory是遍历memblock.memory域中的可以内存,从可用内存空间中划分一段符合预留内存要求的内存空间放到memblock.reserved区域,又因为memblock.memory域中的内存已经被划分为多个段,如果要预留1GB空间的内存时任意一段内存空间可能小于1GB,则需要将预留的内存空间划分为多个小端内存就行预留。如上将1GB的预留内存空间划分为2个512MB,就是为了确保预留内存的成功预留。所以预留内存时,无论划分成了几段预留要需要保证每一段度都预留成功,为了保证预留成功尽可能的将大内存划分为多个小段内存进行预留。

        具体逻辑可以解析__reserved_mem_alloc_in_range()函数。

3. reserved-momery中的no-map属性

        预留的内存如果不想被系统使用,则需要添加no-map属性。该属性保证预留的内存不会在系统内存映射时被映射到虚拟空间。对应代码逻辑:

文件路径:arch/arm64/mm/mmu.c

static void __init map_mem(pgd_t *pgdp)
{
    ……

    //遍历memblock.memory内存region,对符合要求的内存region进行映射
    for_each_mem_range(i, &start, &end) {
        if (start >= end)
        break;

        //对符合要求的memblock.memory内存进行映射
        __map_memblock(pgdp, start, end, pgprot_tagged(PAGE_KERNEL), flags);
    }
    ……
}

        for_each_mem_range定义如下,该宏目的在于变量memblock.memory中的所有内存域,遍历时会调用到should_skip_region()函数,该函数会跳过具有MEMBLOCK_NOMAP标识的内存块,故具有MEMBLOCK_NOMAP标识的内存块不会被进行内存映射

#define for_each_mem_range(i, p_start, p_end) \
__for_each_mem_range(i, &memblock.memory, NULL, NUMA_NO_NODE,        \
     MEMBLOCK_HOTPLUG | MEMBLOCK_DRIVER_MANAGED, \
     p_start, p_end, NULL)

4. 预留的的内存是否会被统计到系统MemTotal中?

        答案是否定的,具有no-map属性reserved-memory预留内存是不是被统计到mem total中。         /poc/meminfo中的MemTotal值来自系统变量_totalram_pages,则从_totalram_pages赋值逻辑可以确认预留内存是否被统计到MemTotal。系统在进行__totalram_pages统计时,因为调用到should_skip_region()函数,具有no-map属性的page会被排除统计。所以给方式预留的内存不会被统计到系统的memtotal中。

        如下函数是给_totalram_pages赋值的部分逻辑:

void __init memblock_free_all(void)
{
    unsigned long pages;
    free_unused_memmap();
    reset_all_zones_managed_pages();

    //统计系统free状态的page数量
    pages = free_low_memory_core_early();

    //将free的page数量添加给_totalram_pages
    totalram_pages_add(pages);
}
static unsigned long __init free_low_memory_core_early(void)

{
    unsigned long count = 0;
    phys_addr_t start, end;
    u64 i;

    memblock_clear_hotplug(0, -1);
    memmap_init_reserved_pages();

    //遍历memblock.memory 和 memblock.reserved两个域内存,遍历时会调用should_skip_region()函
    //数跳过具有MEMBLOCK_NOMAP属性的内存区域,故具有MEMBLOCK_NOMAP标识的内存区域
    //不会被统计到。所以 memblock.momory中具有MEMBLOCK_NOMAP标识的内存区域不会被
    //统计到MemTotal中。另因为有遍历memblock.reserved内存区域,故memblock.reserved中
    //不符合should_skip_region()函数的要求内存区域也可能被统计到MemTotal中
    for_each_free_mem_range(i, NUMA_NO_NODE, MEMBLOCK_NONE, &start, &end, NULL)
    count += __free_memory_core(start, end);

    return count;
}

相关文章:

  • Python基于EdgeTTS库文本转语音
  • 大数据学习(92)-spark详解
  • sqli-labs靶场 less 3
  • CF每日5题Day5(1400)
  • 使用firewall-cmd配置SIP端口转发,实现双网卡互通,内外网方式
  • npm i 出现的网络问题
  • Python Cookbook-4.13 获取字典的一个子集
  • 19.OpenCV图像二值化
  • 【Linux笔记】进程间通信——命名管道
  • 深度学习中的数据类型
  • 17-动规-最长增长子序列
  • leetcode90-子集II
  • 我的编程之旅:从零到无限可能
  • 剖析 Redis 缓存更新策略:保障数据一致性与系统性能的平衡
  • 光传输设备现状
  • 刷题日记day14-字符串-数组去重和排序
  • flutter 专题 七十四 Flutter开发之动画
  • 【Docker镜像】Python项目之使用Dockerfile构建镜像(二)
  • 在Trae中设置Python解释器版本
  • 从零实现3D自动标注:MS3D、MS3D++
  • 招商蛇口:一季度营收约204亿元,净利润约4.45亿元
  • 黄宾虹诞辰160周年|一次宾翁精品的大集结
  • 安徽省公安厅原副厅长刘海石主动投案,正接受审查调查
  • 证券时报:“好房子”标准即将全面落地,购房者有哪些新期待
  • 开门红背后的韧性密码:上海八大企业的“反脆弱”与“真功夫”
  • 央行副行长:我们在研究丰富政策工具箱,将适时推出增量政策