Linux下malloc函数主要用来在用户空间从heap申请内存,申请成功返回指向所分配内存的指针,申请失败返回NULL。默认情况下,Linux内核使用“乐观的”分配内存策略,首先粗略估计系统可使用的内存数,然后分配内存,但是在使用的时候才真正把这块分配的内存给你。这样一来,即使用malloc申请内存没有返回NULL,你也不一定能完全使用这块内存,特别是在一次或连续多次申请很多内存的时候。
如果一直连续用malloc申请内存,而不真正使用,所申请的内存总数可以超过真正可以使用的内存数。但是当真正使用这块内存,比如用memset或bzero函数一次性把所申请到的大块内存“使用掉”,Linux系统就会Out Of Memory,这个时候OOM Killer就会kill掉用户空间的其他进程来腾出更多可使用内存。
OOM Killer根据OOM score来决定kill哪个进程,OOM score可以看/proc/<PID>/oom_score,score由badness函数计算得出,根据进程运行时间长短,进程优先级,进程所使用的内存数等等。可以通过/proc/<PID>/oom_adj来干预计算socre,这个值的取值范围是-17~15,如果是-17该进程就永远不会被kill(这个可能也和内核版本有关,不见得所有内核版本都支持,得实际试试)。
“默认情况”Linux是这种做的,“默认情况”是指/proc/sys/vm/overcommit_memory为0的时候。这个参数也可以调整,如果为1表示“来着不拒”,只要你malloc过来申请,我啥都不做,立马给你分配内存,这样的话性能就会有大幅度的提高;如果为2表示Linux会精确计算所有可使用的内存和所申请的内存,如果所申请的超过的可使用的内存数就返回NULL。可使用的内存值计算方法,虚拟内存(swap)+ /proc/sys/vm/overcommit_memory(百分比) × 物理内存。/proc/sys/vm/overcommit_memory默认值为50,计算起来就是50%的物理内存数。
Linux自身内核会占一部分内存,还有buffer/cache所占用的内存,所以实际上能被malloc申请后使用的内存并非物理内存大小,demsg的输出里面包含了相关信息(如果看不到,可能是被别的信息冲掉了,重启系统,在系统起来后马上看):
Memory: 2071220k/2097152k available (2122k kernel code, 24584k reserved, 884k data, 228k init, 1179584k highmem)