• 内存域水印值:min_free_kbytes


    1、内存域水印值:需要为关键性分配保留的内存空间的最小值;该值保存在全局变量min_free_kbytes中

    2、内存域水印值的计算由函数init_per_zone_pages_min完成:

    /*
     * Initialise min_free_kbytes.
     *
     * For small machines we want it small (128k min).  For large machines
     * we want it large (64MB max).  But it is not linear, because network
     * bandwidth does not increase linearly with machine size.  We use
     *
     * 	min_free_kbytes = 4 * sqrt(lowmem_kbytes), for better accuracy:
     *	min_free_kbytes = sqrt(lowmem_kbytes * 16)
     *
     * which yields
     *
     * 16MB:	512k
     * 32MB:	724k
     * 64MB:	1024k
     * 128MB:	1448k
     * 256MB:	2048k
     * 512MB:	2896k
     * 1024MB:	4096k
     * 2048MB:	5792k
     * 4096MB:	8192k
     * 8192MB:	11584k
     * 16384MB:	16384k
     */
    static int __init init_per_zone_pages_min(void)
    {
    	unsigned long lowmem_kbytes;
    
    	lowmem_kbytes = nr_free_buffer_pages() * (PAGE_SIZE >> 10);
    
    	min_free_kbytes = int_sqrt(lowmem_kbytes * 16);
    	if (min_free_kbytes < 128)
    		min_free_kbytes = 128;
    	if (min_free_kbytes > 65536)
    		min_free_kbytes = 65536;
    	setup_per_zone_pages_min();
    	setup_per_zone_lowmem_reserve();
    	return 0;
    }

    3、setup_per_zone_pages_min设置struct zone的pages_min、pages_low、pages_high成员

    /**
     * setup_per_zone_pages_min - called when min_free_kbytes changes.
     *
     * Ensures that the pages_{min,low,high} values for each zone are set correctly
     * with respect to min_free_kbytes.
     */
    void setup_per_zone_pages_min(void)
    {
    	unsigned long pages_min = min_free_kbytes >> (PAGE_SHIFT - 10);
    	unsigned long lowmem_pages = 0;
    	struct zone *zone;
    	unsigned long flags;
    
    	/* Calculate total number of !ZONE_HIGHMEM pages */
    	for_each_zone(zone) {
    		if (!is_highmem(zone))
    			lowmem_pages += zone->present_pages;
    	}
    
    	for_each_zone(zone) {
    		u64 tmp;
    
    		spin_lock_irqsave(&zone->lru_lock, flags);
    		tmp = (u64)pages_min * zone->present_pages;
    		do_div(tmp, lowmem_pages);
    		if (is_highmem(zone)) {
    			/*
    			 * __GFP_HIGH and PF_MEMALLOC allocations usually don't
    			 * need highmem pages, so cap pages_min to a small
    			 * value here.
    			 *
    			 * The (pages_high-pages_low) and (pages_low-pages_min)
    			 * deltas controls asynch page reclaim, and so should
    			 * not be capped for highmem.
    			 */
    			int min_pages;
    
    			min_pages = zone->present_pages / 1024;
    			if (min_pages < SWAP_CLUSTER_MAX)
    				min_pages = SWAP_CLUSTER_MAX;
    			if (min_pages > 128)
    				min_pages = 128;
    			zone->pages_min = min_pages;
    		} else {
    			/*
    			 * If it's a lowmem zone, reserve a number of pages
    			 * proportionate to the zone's size.
    			 */
    			zone->pages_min = tmp;
    		}
    
    		zone->pages_low   = zone->pages_min + (tmp >> 2);
    		zone->pages_high  = zone->pages_min + (tmp >> 1);
    		setup_zone_migrate_reserve(zone);
    		spin_unlock_irqrestore(&zone->lru_lock, flags);
    	}
    
    	/* update totalreserve_pages */
    	calculate_totalreserve_pages();
    }

    4、setup_per_zone_lowmem_reserve主要用作设置lowmem_reserve值

    /*
     * setup_per_zone_lowmem_reserve - called whenever
     *	sysctl_lower_zone_reserve_ratio changes.  Ensures that each zone
     *	has a correct pages reserved value, so an adequate number of
     *	pages are left in the zone after a successful __alloc_pages().
     */
    static void setup_per_zone_lowmem_reserve(void)
    {
    	struct pglist_data *pgdat;
    	enum zone_type j, idx;
    
    	for_each_online_pgdat(pgdat) {
    		for (j = 0; j < MAX_NR_ZONES; j++) {
    			struct zone *zone = pgdat->node_zones + j;
    			unsigned long present_pages = zone->present_pages;
    
    			zone->lowmem_reserve[j] = 0;
    
    			idx = j;
    			while (idx) {
    				struct zone *lower_zone;
    
    				idx--;
    
    				if (sysctl_lowmem_reserve_ratio[idx] < 1)
    					sysctl_lowmem_reserve_ratio[idx] = 1;
    
    				lower_zone = pgdat->node_zones + idx;
    				lower_zone->lowmem_reserve[j] = present_pages /
    					sysctl_lowmem_reserve_ratio[idx];
    				present_pages += lower_zone->present_pages;
    			}
    		}
    	}
    
    	/* update totalreserve_pages */
    	calculate_totalreserve_pages();
    }

    除数的默认值,对低端内存是256,对高端内存是32

    /*
     * results with 256, 32 in the lowmem_reserve sysctl:
     *	1G machine -> (16M dma, 800M-16M normal, 1G-800M high)
     *	1G machine -> (16M dma, 784M normal, 224M high)
     *	NORMAL allocation will leave 784M/256 of ram reserved in the ZONE_DMA
     *	HIGHMEM allocation will leave 224M/32 of ram reserved in ZONE_NORMAL
     *	HIGHMEM allocation will (224M+784M)/256 of ram reserved in ZONE_DMA
     *
     * TBD: should special case ZONE_DMA32 machines here - in those we normally
     * don't need any ZONE_NORMAL reservation
     */
    int sysctl_lowmem_reserve_ratio[MAX_NR_ZONES-1] = {
    #ifdef CONFIG_ZONE_DMA
    	 256,
    #endif
    #ifdef CONFIG_ZONE_DMA32
    	 256,
    #endif
    #ifdef CONFIG_HIGHMEM
    	 32,
    #endif
    	 32,
    };


  • 相关阅读:
    修改CentOS 6.4 root用户的系统默认语言设置
    Xpages学习
    Mysql 执行sql脚本文件
    Errors occurred during the build. Errors running builder 'JavaScript Validator' on project 'XXX'.
    【鸟哥学习笔记】之一:目录的权限问题
    学习C++的一些问题总结
    C# 一些知识点总结(一)_继承,多态,集合,关键字...
    .NET Framework 框架的一些简单介绍
    Winform窗体关闭时判断是否关闭
    SQL Server 数据库的安全管理(登录、角色、权限)
  • 原文地址:https://www.cnblogs.com/javaadu/p/11742686.html
Copyright © 2020-2023  润新知