项目遇到一个问题,程序跑着跑着就会挂掉,从多方信息分析来看,发现在设备的linux系统中,一个进程申请的内存最大只能达到1GB,而设备所用的物理内存是2GB的。我们的程序有多个进程,但主进程只有一个,里面包括几十个线程,有的线程使用了如opencv的模块,占用内存有几百兆。而之前在文章提到的H.264转AVI,也必须将转码后的AVI格式内容放在内存,由于某些原因,系统中的内存使用峰值会达到1GB。但由于我正在搞其它的bug,这个实际是同事研究出来的,我也只是再次多方面地验证了一下。还是在这里记录一下吧。
测试所用的代码很简单,就是不断地申请内存。
#define BUF_LEN (8*1024*1024)
int main(void)
{
int cnt = 0;
char* p = NULL;
unsigned int total = 0;
while (1)
{
cnt++;
p = (char*)malloc(BUF_LEN);
if (p==NULL)
{
printf("[%d]malloc for %d failed.\n", cnt, BUF_LEN);
break;
}
total += BUF_LEN;
printf("[%d]malloc %p ok total: %u(%.1fKB %.1fMB)\n", cnt, p, total, total/1024.0, total/1024.0/1024.0);
}
return 0;
}
在系统未做配置前,执行上述程序,只能申请900MB的内存。运行结果如下:
[112]malloc 0x7f575008 ok total: 939524096(917504.0KB 896.0MB)
[113]malloc 0x7ed74008 ok total: 947912704(925696.0KB 904.0MB)
[114]malloc 0x7e573008 ok total: 956301312(933888.0KB 912.0MB)
[115]malloc for buff failed.
查找一些资料发现,内存的使用与/proc/sys/vm/overcommit_memory和/proc/sys/vm/overcommit_ratio似乎有关。经过我的测试,似乎和overcommit_memory关系更密切。对于overcommit_memory,我们的设备代码一直都是使用系统的默认值2。在2GB内存系统上只能申请900MB。但是,将它设置为1时,就可以申请最大的内存,执行如下命令临时生效:
echo 1 > /proc/sys/vm/overcommit_memory
再次运行上述程序,结果如下:
[380]malloc 0xbdfd7008 ok total: 3187671040(3112960.0KB 3040.0MB)
[381]malloc 0xbe7d8008 ok total: 3196059648(3121152.0KB 3048.0MB)
[382]malloc 0xbefd9008 ok total: 3204448256(3129344.0KB 3056.0MB)
注:测试中,申请内存的限制与overcommit_ratio的值无关,但修改overcommit_ratio会引起/proc/meminfo的中的值的变化。当overcommit_ratio为10时,信息如下:
cat /proc/meminfo | grep Commit
CommitLimit: 679932 kB
Committed_AS: 495736 kB
当overcommit_ratio为50时,信息如下:
# cat /proc/meminfo | grep Commit
CommitLimit: 1465500 kB
Committed_AS: 495736 kB