aarch32 linux 4.14 busybox-1.30
经常使用free查看mem信息类似如下打印 free 49
total used free shared buffers cached
Mem: 239 189 49 0 0 65
-/+ buffers/cache: 124 115
Swap: 0 0 0
free 命令可以参考busybox 自带的procps
int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM))
{
......
printf(" %12s%12s%12s%12s%12s%12s\n"
"Mem: ",
"total",
"used",
"free",
"shared", "buff/cache", "available" /* swap and total don't have these columns */
);
sysinfo(&info);
/* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */
G.mem_unit = (info.mem_unit ? info.mem_unit : 1);
/* Extract cached and memavailable from /proc/meminfo and convert to mem_units */
seen_available = parse_meminfo(&cached_kb, &available_kb);
available = ((unsigned long long) available_kb * 1024) / G.mem_unit;
cached = ((unsigned long long) cached_kb * 1024) / G.mem_unit;
cached += info.bufferram;
cached_plus_free = cached + info.freeram;
printf(FIELDS_6,
scale(&G, info.totalram), //total
scale(&G, info.totalram - cached_plus_free), //used
scale(&G, info.freeram), //free
scale(&G, info.sharedram), //shared
scale(&G, cached), //buff/cache
scale(&G, available) //available
);
......
}
free 数据的获取是通过sysinfo 系统调用
/**
* do_sysinfo - fill in sysinfo struct
* @info: pointer to buffer to fill
*/
static int do_sysinfo(struct sysinfo *info)
{
......
si_meminfo(info);
......
}
SYSCALL_DEFINE1(sysinfo, struct sysinfo __user *, info)
{
struct sysinfo val;
do_sysinfo(&val);
if (copy_to_user(info, &val, sizeof(struct sysinfo)))
return -EFAULT;
return 0;
}
void si_meminfo(struct sysinfo *val)
{
val->totalram = totalram_pages;
val->sharedram = global_node_page_state(NR_SHMEM);
val->freeram = global_zone_page_state(NR_FREE_PAGES);
val->bufferram = nr_blockdev_pages();
val->totalhigh = totalhigh_pages;
val->freehigh = nr_free_highpages();
val->mem_unit = PAGE_SIZE;
}
global_zone_page_state(NR_FREE_PAGES) 是读取vm_zone_stat 全局变量中的值
另外碰到OOM 问题的时候也会有打印 Normal free:1048kB min:1476kB low:1844kB high:2212kB active_anon:107296kB
adas invoked oom-killer: gfp_mask=0x14200ca(GFP_HIGHUSER_MOVABLE), nodemask=(null), order=0, oom_sco0
adas cpuset=/ mems_allowed=0
CPU: 1 PID: 14889 Comm: adas Tainted: G W 4.14.0-xilinx-g5b58eeb #1
Hardware name: Xilinx Zynq Platform
[<c010f624>] (unwind_backtrace) from [<c010b370>] (show_stack+0x10/0x14)
[<c010b370>] (show_stack) from [<c0827460>] (dump_stack+0x80/0xa0)
[<c0827460>] (dump_stack) from [<c01dd254>] (dump_header+0xa0/0x218)
[<c01dd254>] (dump_header) from [<c01dc8ac>] (oom_kill_process+0x7c/0x484)
[<c01dc8ac>] (oom_kill_process) from [<c01dd108>] (out_of_memory+0x2b8/0x310)
[<c01dd108>] (out_of_memory) from [<c01e16cc>] (__alloc_pages_nodemask+0xa3c/0xe38)
[<c01e16cc>] (__alloc_pages_nodemask) from [<c0208d80>] (handle_mm_fault+0x300/0xb38)
[<c0208d80>] (handle_mm_fault) from [<c0112d40>] (do_page_fault+0x12c/0x32c)
[<c0112d40>] (do_page_fault) from [<c0101268>] (do_DataAbort+0x34/0xb4)
[<c0101268>] (do_DataAbort) from [<c010c19c>] (__dabt_usr+0x3c/0x40)
Exception stack(0xc64dffb0 to 0xc64dfff8)
ffa0: 0056f0e9 a7b5c000 015bc3a4 0159e400
ffc0: 015bc3a4 aaf250fc a24e3010 00000090 00000001 006ee4b8 00000000 3f800000
ffe0: 000000c0 aaf24fe8 b6028665 b6026862 000f0030 ffffffff
Mem-Info:
active_anon:26820 inactive_anon:0 isolated_anon:0
active_file:10 inactive_file:5 isolated_file:0
unevictable:11293 dirty:0 writeback:0 unstable:0
slab_reclaimable:1493 slab_unreclaimable:1802
mapped:3528 shmem:0 pagetables:202 bounce:0
free:262 free_pcp:0 free_cma:4
Node 0 active_anon:107280kB inactive_anon:0kB active_file:40kB inactive_file:20kB unevictable:45172kBs
Normal free:1048kB min:1476kB low:1844kB high:2212kB active_anon:107296kB inactive_anon:0kB active_fiB
lowmem_reserve[]: 0 0 0
Normal: 17*4kB (UM) 2*8kB (U) 37*16kB (M) 5*32kB (M) 1*64kB (M) 0*128kB 1*256kB (M) 0*512kB 0*1024kB B
11299 total pagecache pages
oom打印的free信息的计算方式与free命令的计算方式是否一样呢?
oom 的这条信息与sysrq-m 的信息一样都是同过show_mem函数打印出来的
其中 oom中使用的global_zone_page_state(NR_FREE_PAGES) 与free 命令si_meminfo使用的是同一个函数
void show_mem(unsigned int filter, nodemask_t *nodemask)
{
......
printk("Mem-Info:\n");
show_free_areas(filter, nodemask);
......
}
void show_free_areas(unsigned int filter, nodemask_t *nodemask)
{
......
printk("active_anon:%lu inactive_anon:%lu isolated_anon:%lu\n"
" active_file:%lu inactive_file:%lu isolated_file:%lu\n"
" unevictable:%lu dirty:%lu writeback:%lu unstable:%lu\n"
" slab_reclaimable:%lu slab_unreclaimable:%lu\n"
" mapped:%lu shmem:%lu pagetables:%lu bounce:%lu\n"
" free:%lu free_pcp:%lu free_cma:%lu\n",
global_node_page_state(NR_ACTIVE_ANON),
global_node_page_state(NR_INACTIVE_ANON),
global_node_page_state(NR_ISOLATED_ANON),
global_node_page_state(NR_ACTIVE_FILE),
global_node_page_state(NR_INACTIVE_FILE),
global_node_page_state(NR_ISOLATED_FILE),
global_node_page_state(NR_UNEVICTABLE),
global_node_page_state(NR_FILE_DIRTY),
global_node_page_state(NR_WRITEBACK),
global_node_page_state(NR_UNSTABLE_NFS),
global_node_page_state(NR_SLAB_RECLAIMABLE),
global_node_page_state(NR_SLAB_UNRECLAIMABLE),
global_node_page_state(NR_FILE_MAPPED),
global_node_page_state(NR_SHMEM),
global_zone_page_state(NR_PAGETABLE),
global_zone_page_state(NR_BOUNCE),
global_zone_page_state(NR_FREE_PAGES),
free_pcp,
global_zone_page_state(NR_FREE_CMA_PAGES));
......
}
所以两者相同
free:262 free_pcp:0 free_cma:4
以page为单位,板子只有一个normal zone 所以 262*4K(page size) = 1048K
Normal free:1048kB min:1476kB low:1844kB high:2212kB active_anon:107296kB