近似计算:
MemAvailable ≈ MemFree - LowWaterMark + (PageCache - min(PageCache / 2, LowWaterMark))
min_free_kbytes low = min × 5 / 4; high = min × 3 / 2;
当 cache 很小的时候,MemAvailable < MemFree
MemAvailable
有些应用程序会根据系统的可用内存大小自动调整内存申请的多少,所以需要一个记录当前可用内存数量的统计值,MemFree并不适用,因为MemFree不能代表全部可用的内存,系统中有些内存虽然已被使用但是可以回收的,
比如cache/buffer、slab都有一部分可以回收,所以这部分可回收的内存加上MemFree才是系统可用的内存,即MemAvailable。/proc/meminfo中的MemAvailable是内核使用特定的算法估算出来的,要注意这是一个估计值,并不精确。
kernel code 分析
available = free - totalreserve + pagecache - min(pagecache / 2, wmark_low) + reclaimable - min(reclaimable / 2, wmark_low);
max = zone->lowmem_reserve[j]
max += high_wmark_pages(zone)
totalreserve_pages += max
available = global_zone_page_state(NR_FREE_PAGES) - totalreserve_pages
wmark_low += low_wmark_pages(zone)
pagecache = pages[LRU_ACTIVE_FILE] + pages[LRU_INACTIVE_FILE];
pagecache -= min(pagecache / 2, wmark_low)
available += pagecache
reclaimable = global_node_page_state_pages(NR_SLAB_RECLAIMABLE_B) +
global_node_page_state(NR_KERNEL_MISC_RECLAIMABLE);
available += reclaimable - min(reclaimable / 2, wmark_low);
参考代码
fs/proc/meminfo.c
meminfo_proc_show
available = si_mem_available()
mm/page_alloc.c
si_mem_available
MemTotal
系统从加电开始到引导完成,firmware/BIOS要保留一些内存,kernel本身要占用一些内存,
最后剩下可供kernel支配的内存就是MemTotal。这个值在系统运行期间一般是固定不变的
dmesg中记录上电内存分配
available = 物理内存 – absent – reserved
reserved 包括 kernel code, data 和 init,由于它还包括initrd和其它更多的内容,所以reserved远远大于 kernel code + data + init 之和。