32位系统有HIGHMEM_ZONE而64位没有HIGHMEM_ZONE的原因

本文探讨了32位系统中存在HIGHMEM_ZONE的原因,由于32位系统地址空间限制,需要动态映射高端内存。而在64位系统,尤其是ARM64架构下,由于更大的地址空间,可以直接映射全部物理内存,从而无需HIGHMEM_ZONE。

查阅过很多的blog或者相关书,都说64位系统的空间足够所以不需要HIGHMEM ZONE,对于这句话一直是一知半解,今天仔细看了下相关的config,理解如下:

高端内存的由来:

在32位系统中总的地址空间是4GB,按照地址划分3G~4G为内核空间,0~3G为用户空间,此时PAGE_OFFSET为0xC0000000.如果物理内存的size为4GB,则后面3GB内核就无法访问,为了满足此要求,在内核1GB空间分出了一定的空间来进行映射。

Linux将内核地址空间划分为三部分ZONE_DMA、ZONE_NORMAL和ZONE_HIGHMEM,以手上某平台2GB RAM,32位系统的手机为例,通过开机的kernel log可以看到系统虚拟内存的映射如下:

[    0.000000] <0>    vector  : 0xffff0000 - 0xffff1000   (   4 kB)
[    0.000000] <0>    fixmap  : 0xffc00000 - 0xfff00000   (3072 kB)
[    0.000000] <0>    vmalloc : 0xe1000000 - 0xff800000   ( 488 MB)
[    0.000000] <0>    lowmem  : 0xc0000000 - 0xe0800000   ( 520 MB)
[    0.000000] <0>    pkmap   : 0xbfe00000 - 0xc0000000   (   2 MB)
[    0.000000] <0>    modules : 0xbf000000 - 0xbfe00000   (  14 MB)
[    0.000000] <0>      .text : 0xc0008000 - 0xc1000000   (16352 kB)
[    0.000000] <0>      .init : 0xc1600000 - 0xc1800000   (2048 kB)
kernel-4.19水线计算代码:static void __setup_per_zone_wmarks(void) { unsigned long pages_min = min_free_kbytes >> (PAGE_SHIFT - 10); unsigned long pages_low = extra_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->managed_pages; } for_each_zone(zone) { u64 min, low; spin_lock_irqsave(&zone->lock, flags); min = (u64)pages_min * zone->managed_pages; do_div(min, lowmem_pages); low = (u64)pages_low * zone->managed_pages; do_div(low, vm_total_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 WMARK_HIGH-WMARK_LOW and (WMARK_LOW-WMARK_MIN) * deltas control asynch page reclaim, and so should * not be capped for highmem. */ unsigned long min_pages; min_pages = zone->managed_pages / 1024; min_pages = clamp(min_pages, SWAP_CLUSTER_MAX, 128UL); zone->watermark[WMARK_MIN] = min_pages; } else { /* * If it's a lowmem zone, reserve a number of pages * proportionate to the zone's size. */ zone->watermark[WMARK_MIN] = min; } /* * Set the kswapd watermarks distance according to the * scale factor in proportion to available memory, but * ensure a minimum size on small systems. */ min = max_t(u64, min >> 2, mult_frac(zone->managed_pages, watermark_scale_factor, 10000)); #if defined(CONFIG_OPLUS_UXMEM_OPT) && defined(OPLUS_FEATURE_SCHED_ASSIST) \ && defined(CONFIG_OPLUS_FEATURE_SCHED_ASSIST) if (ux_page_pool_enable) { zone->watermark[WMARK_MIN] = zone->watermark[WMARK_MIN]*2; } #endif zone->watermark[WMARK_LOW] = min_wmark_pages(zone) + low + min; zone->watermark[WMARK_HIGH] = min_wmark_pages(zone) + low + min * 2; spin_unlock_irqrestore(&zone->lock, flags); } /* update totalreserve_pages */ calculate_totalreserve_pages(); } kernel-6.6水线计算代码:static void __setup_per_zone_wmarks(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 pages below ZONE_HIGHMEM */ for_each_zone(zone) { if (zone_idx(zone) <= ZONE_NORMAL) lowmem_pages += zone_managed_pages(zone); } for_each_zone(zone) { u64 tmp; spin_lock_irqsave(&zone->lock, flags); tmp = (u64)pages_min * zone_managed_pages(zone); do_div(tmp, lowmem_pages); if (zone_idx(zone) > ZONE_NORMAL) { /* * __GFP_HIGH and PF_MEMALLOC allocations usually don't * need pages from zones above ZONE_NORMAL, so cap * pages_min to a small value here. * * The WMARK_HIGH-WMARK_LOW and (WMARK_LOW-WMARK_MIN) * deltas control async page reclaim, and so should * not be capped for highmem and movable zones. */ unsigned long min_pages; min_pages = zone_managed_pages(zone) / 1024; min_pages = clamp(min_pages, SWAP_CLUSTER_MAX, 128UL); zone->_watermark[WMARK_MIN] = min_pages; } else { /* * If it's a lowmem zone, reserve a number of pages * proportionate to the zone's size. */ zone->_watermark[WMARK_MIN] = tmp; } /* * Set the kswapd watermarks distance according to the * scale factor in proportion to available memory, but * ensure a minimum size on small systems. */ tmp = max_t(u64, tmp >> 2, mult_frac(zone_managed_pages(zone), watermark_scale_factor, 10000)); zone->watermark_boost = 0; zone->_watermark[WMARK_LOW] = min_wmark_pages(zone) + tmp; zone->_watermark[WMARK_HIGH] = low_wmark_pages(zone) + tmp; zone->_watermark[WMARK_PROMO] = high_wmark_pages(zone) + tmp; trace_android_vh_init_adjust_zone_wmark(zone, tmp); spin_unlock_irqrestore(&zone->lock, flags); } /* update totalreserve_pages */ calculate_totalreserve_pages(); } 总结提供两者的计算公式,找出差异点
最新发布
07-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值