• 内存管理-初始化【代码】


    build_all_zonelists

    该函数在系统初始化阶段建立每个node下的zonelist结构

     函数第3行:设置初始化每一个node下zonelist的策略:举个例子说明:x86_64架构,64位系统下,假设系统中有node0和node1,node0中有DMA,DMA32,NORMAL,MOVABLE四个内存去,node1中有NORMAL,MOVABLE两个内存区。假设node0的初始化zonelist由一下两种方案:

    第一种方案:[node0(MOVABLE),node0(NORMAL),node0(DMA32),node(DMA),node1(MAVABLE),node1(NORMAL)]

    第二种方案:[node0(MOVABLE),node1(MOVABLE),node0(NORMAL),node1(NORMAL),node0(DMA32),node0(DMA)]

    根据buddy系统的zone的fallback规则:

    第一种方案考虑的时优先分配举例比较近的cpu,这样会加快cpu每次内存的访问速度;但是缺点是:会加快DMA32和DMA内存区的消耗,例如:当分buddy系统选中node0作为分配节点时,第一种方案对于要分配normal区和movable区的请求,如果node0上这两个区内存紧张,就会fallback到node0的DMA32和DMA区。如果DMA,DMA32内存去内存过渡消耗(本身这两个内存去空间就比较小DMA为固定16M,DMA32固定为4G)到真正必须要从DMA,DMA32分配内存时,就很容易出发OOM.

    第二种方案优先考虑了减少内存分配请求对DMA,DMA32内存区的压力,次优先考虑了node节点之间的距离,这样会降低cpu每次访问内存的熟读。原因:还用上面的例子:如果node0上的movable和normal区紧张时,会优先分被fallback到node1上的movable和normal区,只有node0和node1上的normal,movable都紧张时,才会fallback到DMA和DMA32区。这样就减少了因”必须要申请DMA,DMA32内存去内存而失败的概率。

    内核的做法:

    1.默认由一个规则通过内核的内存现状选择上面的一种方案来初始化node的zonelist

    2.导出了配置文件到proc文件系统或者通过sysctl命令来让用户自己设定使用种方案来初始化node的zonelist

    第3行的逻辑:如果用户通过sysctl或者proc设置了zonelist初始化的策略,就用用户的设置,如果没有就根据系统种的内存情况选择两种方案种的一种(具体怎么选择看下文关于:default_zonelist_order的介绍

    接下来重点说一下第15行到第26行的逻辑(TODO:补充完整对本函数的说明

    第16行计算了所有zone中高于high内存水线的页数(举个例子:假设系统中只有两个zone,zone0总共由10个页,zone1总共由15个页,zone0的high水线时5,zone1的high水线时8,那么vm_total_pages就等于(10-5+15-8))第23行到第26行初始化了一个重要的全局变量:page_group_by_mobility_disabled,这个全局变量内核没有提供用户态接口,并且这里设置后,整个系统运行期间没有办法改变。也就是说如果系统中所有zone中高于内存水线的总页数如果小于pageblock_nr_pages*MIGRATE_TYPE那么就关闭按页的移动性分组的功能。相反则开启该功能。

    【注】作者见过的所有生产环境中(通用服务器):vm_total_pages都远远大于pageblock_nr_pages*MIGRATE_TYPES,因此在通用服务器应用场景可以认为page_group_by_mobility_disabled始终等于0(可能有些嵌入式系统中内存比较少时,会为1)

    void build_all_zonelists(void)
    {
    	set_zonelist_order();
    
    	if (system_state == SYSTEM_BOOTING) {
    		__build_all_zonelists(NULL);
    		mminit_verify_zonelist();
    		cpuset_init_current_mems_allowed();
    	} else {
    		/* we have to stop all cpus to guarantee there is no user
    		   of zonelist */
    		stop_machine(__build_all_zonelists, NULL, NULL);
    		/* cpuset refresh routine should be here */
    	}
    	vm_total_pages = nr_free_pagecache_pages();
    	/*
    	 * Disable grouping by mobility if the number of pages in the
    	 * system is too low to allow the mechanism to work. It would be
    	 * more accurate, but expensive to check per-zone. This check is
    	 * made on memory-hotadd so a system can start with mobility
    	 * disabled and enable it later
    	 */
    	if (vm_total_pages < (pageblock_nr_pages * MIGRATE_TYPES))
    		page_group_by_mobility_disabled = 1;
    	else
    		page_group_by_mobility_disabled = 0;
    
    	printk("Built %i zonelists in %s order, mobility grouping %s.  "
    		"Total pages: %ld
    ",
    			nr_online_nodes,
    			zonelist_order_name[current_zonelist_order],
    			page_group_by_mobility_disabled ? "off" : "on",
    			vm_total_pages);
    #ifdef CONFIG_NUMA
    	printk("Policy zone: %s
    ", zone_names[policy_zone]);
    #endif
    }
    

    default_zonelist_order  

    --------------------------------------------------------------------------------------------------

    TODO1:

  • 相关阅读:
    [javaSE] GUI(jar包双击运行)
    [javaSE] GUI(打开文件对话框)
    [javaSE] GUI(菜单)
    [javaSE] GUI(对话框Dialog)
    [javaSE] GUI(练习-列出指定目录内容)
    [javaEE] 控制浏览器缓存资源
    [javaEE] response实现图片下载
    [javaSE] GUI(鼠标事件)
    [javaSE] 网络编程(TCP-并发上传图片)
    [javaSE] IO流(装饰设计模式)
  • 原文地址:https://www.cnblogs.com/DoOrDie/p/10247387.html
Copyright © 2020-2023  润新知