popen error:Cannot allocate memory原因分析

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档



前言

        这是在实际项目中发现的bug,设备运行一段时间后出现报错:popen error:Cannot allocate memory。运行平台:新唐NUC970,内存64M ,linux内核版本:3.10.108+ 。



一、popen介绍

        popen函数会创建了一个子进程来执行 shell,而 shell 又创建了一个子进程来执行命令,从实践过程可以看到,在进程分配内存沾满进程stack空间后,这些函数都是执行失败,返回ENOMEM 错误码Cannot allocate memory,只要不释放空间,都是一直执行失败的


二、popen error 原因分析

         这里做了一个测试程序,复现问题:主线程malloc申请堆空间,把进程的堆栈空间沾满;另外一条线程执行popen操作。结果是:routine线程执行popen一直报popen error:Cannot allocate memory错误,直到主线程执行free操作。

1、设备的系统内存


 2、运行测试程序./test  ,MAX statck size刚好是8M

 3、结果:在进程运行过程,使用堆空间超过8M后,就报错了,但是实际上系统内的内存还很充足,还有37M多的。

 4、一旦把malloc申请的空间释放后,马上恢复正常

5、测试程序源码

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/sysinfo.h>

#define SIZE (1024*1024*1)
#define MEM_SIZE (45)

void *routine(void *arg)
{
	struct sysinfo info;
	
	while(1)
	{		
		sysinfo(&info);
		printf("freeram = %ld\n",info.freeram);
		
		FILE* fp = popen("cat /sys/class/net/eth0/carrier", "r");
		if(fp == NULL)
		{
			printf("popen error:%s\n", strerror(errno));
			sleep(1);
			continue;
		}
		
		char  buffer[1024];
		int   bytes_read = fread(buffer, 1, sizeof(buffer), fp);
		pclose(fp);

		printf("popen ok %2x\n",buffer[0]);			
		sleep(1);
		
	}
}

int main(int argc, char **argv)
{
		
	pthread_t tid;
	pthread_create(&tid, NULL, routine, NULL);
	

	unsigned int *p = (unsigned int *)malloc(1024 * 1024 * MEM_SIZE);
	printf("malloc buffer: %p\n", p);

	for (int i = 0; i < 1024 * 1024 * (MEM_SIZE/sizeof(int)); i++) 
	{
		p[i] = 123;
		if ((i & 0xFFFFF) == 0) 
		{
			printf("%dMB written\n", i >> 18);
			sleep(1);
			//usleep(100000);
		}

	}

	
	while(1)
	{
		sleep(20);
		if(p)
		{
			printf("free mem\n"); //内存释放后popen调用正常
			free(p);
			p = NULL;
		}
	}
	
	return 0;
}


总结

        popen这类函数系统开销很大,再进程内存紧张的情况下,很容易出错,没有及时把申请的内存空间释放,就一直执行失败的。解决办法下篇再讲解哦~~~

猜你喜欢

转载自blog.csdn.net/qq_26622451/article/details/121249502
今日推荐