最新消息:XAMPP默认安装之后是很不安全的,我们只需要点击左方菜单的 "安全"选项,按照向导操作即可完成安全设置。

Linux的物理内存模型

XAMPP案例 中文小张 702浏览 0评论

在Linux的物理内存模型中,一个内存node按照属性被划分为了多个zones,比如ZONE_DMA和ZONE_NORMAL,在32位系统中,还有ZONE_HIGHMEM。如果没有通过GFP标志位做出限定,那么当ZONE_HIGHMEM中内存不足时,可从更低位的ZONE_NORMAL中分配,ZONE_NORMAL中内存不足时,可从更低位的ZONE_DMA中分配。这里的“低位”是指zone的物理内存的地址更小。
这里所谓的“不足”就是当前zone的空余内存低于了本次内存分配的请求大小。除了最高位的ZONE_HIGHMEM,其他zones都会为比它更高位的zone单独划分出一片内存作为预留,这部分内存被称作”lowmem reserve”。如果说上文讲的watermark是zone保有的自留田,那么这个”lowmem reserve”就是给高位zones提供的后花园。
当你查看”/proc/sys/vm/lowmem_reserve_ratio”的值时,会得到一组类似这样的输出:

设ZONE_DMA, ZONE_NORMAL和ZONE_HIGHMEM的内存大小分别是A, B和C,那么在ZONE_DMA中,需要给ZONE_NORMAL和ZONE_HIGHMEM预留的内存大小分别是B/256和(B+C)/256。在ZONE_NORMAL中,需要给ZONE_HIGHMEM预留的内存大小是C/32。分母来自于zone自己的”lowmem_reserve_ratio”,而分子则来自于其他的zones。

在Linux的实现中,是以struct zone中的lowmem_reserve[MAX_NR_ZONES]来表示这种预留内存的。同上文讲的watermark一样,也是以page为计算单位的。如果这3个zones的大小分别是16MiB, 784MiB和200MiB,且page的大小是4KiB,根据1MiB包含256个pages,那么这3个zones就分别包含4096, 190464, 51200个pages。

所以,ZONE_DMA给ZONE_NORMAL预留的将是190464/256=784个pages,给ZONE_HIGHMEM预留的将是(190464+51200)/256=984个pages。ZONE_NORMAL给ZONE_HIGHMEM预留的则是51200/32=1600个pages。这种关系可以用一个3×3的矩阵来表示:

可通过”cat /proc/zoneinfo”中的”protection”部分查看各个zones预留pages的数目,这里叫”protection”是由于历史原因,因为早期开发lowmem_reserve功能时用的名称就是”protection”。

设置每个zone的lowmem_reserve[]的函数是setup_per_zone_lowmem_reserve():

static void setup_per_zone_lowmem_reserve(void){
for (j = 0; j < MAX_NR_ZONES; j++) {
struct zone *zone = pgdat->node_zones + j;
unsigned long managed_pages = zone_managed_pages(zone);

idx = j;
while (idx) {
struct zone *lower_zone;

idx–;
lower_zone = pgdat->node_zones + idx;

if (sysctl_lowmem_reserve_ratio[idx] < 1) {
sysctl_lowmem_reserve_ratio[idx] = 0;
lower_zone->lowmem_reserve[j] = 0;
} else {
lower_zone->lowmem_reserve[j] =
managed_pages / sysctl_lowmem_reserve_ratio[idx];
}
managed_pages += zone_managed_pages(lower_zone);
}
}

calculate_totalreserve_pages();}

结合上面的示例,这段代码的逻辑可以用下图表示:

当ZONE_HIGHMEM内存不足,分配fail的时候,就将”fallback”到ZONE_NORMAL,尝试从ZONE_NORMAL给它预留的1600个pages中分配,如果还不够,就要继续”fallback”到ZONE_DMA,从ZONE_DMA给它预留的984个pages中分配。

同理,当ZONE_NORMAL内存不足时,就会”fallback”到ZONE_DMA,尝试从ZONE_DMA给它预留的784个pages中分配。

ZONE_NORMAL和ZONE_DMA都是线性映射,使用方便,ZONE_DMA还可以满足一些特殊的DMA设备对地址的要求,所以我们通常是希望尽量不要动用低位zones的内存的。当不可避免地需要”fallback”时,得看下低位zones本身的空余内存是否充足。

只有一个zone空余内存的值大于它自己的watermark[WMARK_HIGH]值加上给某个高位zone预留的内存值,才算是“充足”的,对应的高位zone才可以从这个低位zone中截取内存。也就是说,低位zone会优先保证自己的内存分配,确实有一定的富余的情况下,才可以提供给更高位的zones。

假设现在系统的内存统计情况如下:

因为1000>100+784,而2000<500+1600,所以此时ZONE_NORMAL到ZONE_DMA的”fallback”是可以成功的,而ZONE_HIGHMEM到ZONE_NORMAL的”fallback”则不可以。

在setup_per_zone_lowmem_reserve()的代码最后,还有个calculate_totalreserve_pages(),这里”totalreserve”是指所有zones的high watermark加上lowmem_reserve[]的值,因为不管是“自留田”还是“后花园”,都是一个zone需要预留的内存。

ZONE_DMA和ZONE_DMA32默认的”lowmem_reserve_ratio”的值是256,其他zones的默认值是32。如果你的系统中低位zones的内存占比较大,那么可以将这个ratio值调小一些,也就是预留更多的内存给高位zones,反之则可以调大一些。

转载请注明:XAMPP中文组官网 » Linux的物理内存模型

您必须 登录 才能发表评论!