lowmem_reserve的作用
kernel在分配内存时,可能会涉及到多个zone,分配会尝试从zonelist第一个zone分配,如果失败就会尝试下一个zone。我们可以想像应用进程通过内存映射申请Highmem 并且加mlock分配,如
果此时Highmem zone无法满足分配,则会尝试从Normal进行分配。这就有一个问题,来自Highmem的请求可能会耗尽Normal zone的内存,而且由于mlock又无法回收,最终的结果就是Normal zone无内存提供给kernel的正常分配,而Highmem有大把的可回收内存无法有效利用。
lowmem_reserve怎么用
调试环境中的情况如下:
3种内存区大小如下:
DMA ZONE: 0x1000个页帧
NORMAL ZONE: 0x37000个页帧
HIGH ZONE: 0x44ffd个页帧
内存分配策略有如下3种:
pgdat->node_zonelists[0]----------------->策略1
pgdat->node_zonelists[1]----------------->策略2
pgdat->node_zonelists[2]----------------->策略3
策略1:
pgdat->node_zonelists[0].zones[0]=zone+1
pgdat->node_zonelists[0].zones[1]=zone+0
说明:先分配normal zone页,然后dma zone页
策略2:
pgdat->node_zonelists[1].zones[0]=zone+0
说明:先分配dma zone页。
策略3:
pgdat->node_zonelists[2].zones[0]=zone+2
pgdat->node_zonelists[2].zones[1]=zone+1
pgdat->node_zonelists[2].zones[2]=zone+0
说明:先分配high zone页,然后normal zone页.,然后dma页。
lowmem_reserve数组值如下:
DMA ZONE:
lowmem_reserve[0]=0
lowmem_reserve[1]=0x370
lowmem_reserve[2]=0x7bf
NORMAL ZONE:
lowmem_reserve[0]=0x0
lowmem_reserve[1]=0x0
lowmem_reserve[2]=0x227f
HIGHZONE:
lowmem_reserve[0]=0x0
lowmem_reserve[1]=0x0
lowmem_reserve[2]=0x0
说明:
如果想申请高端内存会使用策略3,显然HIGH ZONE中lowmem_reserve[2]=0x0,就是没有限制;如果HIGH ZONE的内存不够,则到NORMAL ZONE分配内存,lowmem_reserve[2]=0x227f;意思说必须给NORMAL ZONE保留0x227f个页帧内存;如果NORMAL ZONE区内存也不够分配,则到DMA ZONE分配内存,意思说必须给DMA ZONE保留0x7bf个页帧。
如果想申请普通内存会使用到策略1,显然NORMAL ZONE中lowmem_reserve[1]=0x0,就是没有限制;如果NORMAL ZONE的内存不够,则到DMA ZONE分配内存,lowmem_reserve[1]=0x370,意思说必须给DMA ZONE保留0x370个页帧。
zone[i]------>lowmem_reserve[j]=k:初始分配j zone的内存,到i zone分配的时候,需要保留多少k个页帧给i zone。
补充:
i=j=0----------->DMA ZONE
i=j=1----------->NORMAL ZONE
i=j=2----------->NORMAL ZONE
lowmem_reserve赋值
1978 static void setup_per_zone_lowmem_reserve(void)
1979 {
1980 struct pglist_data *pgdat;
1981 int j, idx;
1982
1983 printk(KERN_ERR "tom %s(%s:%u)\n", __FUNCTION__, __FILE__, __LINE__);
1984 for_each_pgdat(pgdat) {
1985 for (j = 0; j < MAX_NR_ZONES; j++) {
1986 struct zone * zone = pgdat->node_zones + j;
1987 unsigned long present_pages = zone->present_pages;
1988
1989 zone->lowmem_reserve[j] = 0;
1990
1991 printk(KERN_ERR "tom zone->lowmem_reserve[%x]=%x\r\n",j,zone->lowmem_reserve[j]);
1992 for (idx = j-1; idx >= 0; idx--) {
1993 struct zone * lower_zone = pgdat->node_zones + idx;
1994
1995 lower_zone->lowmem_reserve[j] = present_pages / sysctl_lowmem_reserve_ratio[idx];
1999 present_pages += lower_zone->present_pages;
2001 }
2002 }
2003 }
2004 }
函数调用:
1)初始化调用,init_per_zone_pages_min—>setup_per_zone_lowmem_reserve。
2)在文件系统输入:echo “100 100”/proc/sys/vm/lowmem_reserve_ratio,也会调用。