즉시 사용 가능 : 작은 도구를 공유하여 메모리 누수 확인

【기능 설명】

        임베디드 시스템 애플리케이션을 개발하는 동안 메모리 누출은 매우 심각하고 골치 아픈 문제입니다. 물론 메모리 누수를 확인하기위한 많은 전문 도구와 소프트웨어가 있습니다. 저는 memwatch와 valgrind를 더 많이 사용합니다.

        이러한 도구는 주로 개발 과정에서 메모리 누수를 확인하는 데 사용됩니다. 그러나 모든 프로그램이 개발되고 통합 테스트가 시작되면 여전히 시스템 리소스가 지속적으로 감소하는 것으로 확인되면 어떻게 처리할까요?

        여기에 제공된 작은 도구는 이러한 상황을 처리하는 데 사용됩니다. 메모리 누수가 의심되는 프로세스에서 사용하는 시스템 리소스를 모니터링 할 수 있습니다.

        특히 시스템이 여러 사람에 의해 개발되고 여러 프로세스로 구성된 경우 리소스 누출이 발생하면 누가 먼저 의심해야한다고 생각하십니까? 누가 자신의 프로그램에 문제가 있는지 먼저 확인해야합니까? 랭 글링이 자주 일어나고 작은 친구들 사이의 소원이 잠재 의식에 씨앗을 심었습니다.

        이 시점에서 모니터링 프로그램이 출력하는 데이터가 가장 유용합니다!

 

 

【테스트 환경】

1. x86 시스템

    시스템과 함께 제공되는 gcc 컴파일러를 사용하여 Ubuntu 16.04에서 테스트했습니다.

2. 임베디드 시스템

    컴파일러를 해당하는 크로스 컴파일러로 변경하십시오.

 

【코드 다운로드】

1. 스카이 드라이브

    https://pan.baidu.com/s/1yNrjQ6var8xokAJWEsFYFw  

    passwd : uqbh

 

2. 파일 설명

    핵심 코드는 memory_trace.c 파일 하나이고 다른 두 파일은 컴파일 스크립트입니다.

/**
 * @brief: 这个小工具用来监控系统中一些进程的资源使用情况,
 *			可以用来检查程序中是否存在内存泄露。
 * 
 * @author: 微信 captain5780
 * @email:  [email protected]
 *
 * @note: ./memory_trace <进程名称1> <进程名称2> <进程名称3>
 */

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define TRACE_ITEM_NUM		4
#define PROCESS_MAX			20
#define PROCESS_NAME_LEN	128
#define BUF_LEN				512

// 需要监控的资源名称
char *TraceItem[TRACE_ITEM_NUM] = 
	{"VmSize", "VmRSS", "VmStk", "VmData"};

// 保存需要监控的进程名称
char *ProcessList[PROCESS_MAX];

// 打印消息,在实际项目中可以利用 zlog 等日志工具来记录到文件系统中。
static void log_msg(const char *msg)
{
	printf("%s", msg);
}

int main(int argc, char *argv[])
{
	// 检查最大监控的进程个数
	if (argc >= PROCESS_MAX) {
		printf("too many process \n");
		exit(-1);
	}

	// 提取命令行参数传入的进程名称,保存在 ProcessList 中。
	int i, k, count;
	for (i = 0, count = 0; i < argc - 1; i++) {
		count++;
		ProcessList[i] = (char *)malloc(PROCESS_NAME_LEN);
		memset(ProcessList[i], 0, PROCESS_NAME_LEN);
		sprintf(ProcessList[i], "%s", argv[i + 1]);
	}

	time_t rawtime;
	struct tm *timeinfo;
	char *buf = (char *)malloc(BUF_LEN);

	while (1) {
		// 记录当前的时间
		time(&rawtime);
		timeinfo = localtime(&rawtime);
		memset(buf, 0, BUF_LEN);
		sprintf(buf, "\n[%02d:%02d:%02d] \n",
				timeinfo->tm_hour, 
				timeinfo->tm_min, 
				timeinfo->tm_sec);
		log_msg(buf);

		// 此for循环用于获取监控进程的资源占用情况
		for (i = 0; i < count; i++) {
			memset(buf, 0, BUF_LEN);
			sprintf(buf, "[%s] \n", ProcessList[i]);
			log_msg(buf);

			for (k = 0; k < TRACE_ITEM_NUM; k++) {
				memset(buf, 0, BUF_LEN);
				// 获取进程ID号: 执行系统命令,然后读取输出结果。
				sprintf(buf, 
				    "ps -aux | grep %s | grep -v grep | awk '{print $2}'", 
				    ProcessList[i]);
				FILE *fp = popen(buf, "r");
				if (NULL == fp) {
					printf("popen failed! \n");
					continue;
				}

				char line[128] = { 0 };
				fgets(line, 128, fp);
				int len = strlen(line);
				if (*(line + len - 1) == '\n')
					*(line + len - 1) = 0;
				pclose(fp); 

				// 根据进程ID号,获取该进程的堆栈信息。
				memset(buf, 0, BUF_LEN);
				sprintf(buf, 
						"cat /proc/%s/status | grep %s | grep -v grep", 
						line, TraceItem[k]);
				
				fp = popen(buf, "r");
				if (NULL == fp) {
					printf("popen failed! \n");
					continue;
				}
				fgets(line, 128, fp);
				pclose(fp);
				log_msg(line);   // 记录到日志
			}
		}

		// 获取系统的空闲资源信息
		memset(buf, 0, BUF_LEN);
		sprintf(buf, "free | grep Mem: | grep -v grep");
		FILE *fp = popen(buf, "r");
		if (NULL == fp) {
			printf("popen failed! \n");
			continue;
		}

		char line[128] = { 0 };
		fgets(line, 128, fp);
		pclose(fp);
		log_msg(line);

		sleep(5);    // 间隔一段时间
	}

	// 释放 malloc 分配的堆空间
	free(buf);

	for (i = 0; i < PROCESS_MAX; i++) {
		if (ProcessList[i])
			free(ProcessList[i]);
	}

	return 0;
}

3. 인쇄물

    이 도구의 기능은 실제로 매우 간단합니다. 즉, 시스템 명령을 호출하여 프로세스가 차지하는 시스템 리소스를 모니터링합니다.

 

    특히, 계속해서 출력합니다 : / proc / [pid] / status의 내용. 이 파일에는 4 개의 주요 표시기가 있으며 여기에 간략하게 나열되어 있으며 특정 의미를 검색 할 수 있습니다.

    VmSize (KB) : 프로세스에서 사용하는 가상 메모리 크기입니다.

    VmRSS (KB) : 물리적 메모리에 상주하고 하드 디스크로 스왑되지 않는 프로세스의 일부입니다.

    VmStk (KB) : 프로세스에서 사용하는 스택의 크기입니다.

    VmData (KB) : 프로세스 데이터 세그먼트의 크기.

 

[이 가제트를 작성하는 이유]

 이전에 3 개의 대형 모듈이 포함 된 사물 인터넷 용 게이트웨이 제품에 대해 썼는데,이 제품은 서로 다른 사람이 처리합니다. 최악은이 세 사람 중 한 명은 일본에 있고 한 명은 대만에, 다른 한 명은 우리.

 

    통합 테스트 중에 시스템 리소스가 지속적으로 감소하고 규칙 성이 발견되지 않았습니다. 프로세스간에 많은 상호 작용이 있기 때문에 특정 특정 실행 논리가 트리거 될 때만 메모리 누수가 발생할 수 있습니다.

 

    범인을 찾기 위해이 작은 도구를 작성했습니다. 약 2 일의 실행 후 문제의 원인을 신속하게 찾았습니다.

 

[발생할 수있는 문제]

1. 시스템 지침

    프로그램에는 proc, grep, awk, free와 같은 여러 시스템 명령이 사용됩니다.

    다른 임베디드 시스템에서 이러한 명령어의 출력 형식은 다를 수 있으며,이 도구를 직접 실행하는 출력에 문제가있는 경우 코드의 명령어 구문 분석 부분을 조정해야합니다.

 

2. 조정 방법

    예 : 코드에서 다음 명령어를 사용하여 프로세스 이름에 따라 프로세스 ID를 가져옵니다. ps -aux | grep % s | grep -v grep | awk '{print $ 2}'

   ps 명령의 경우 시스템에 -aux 속성이 필요하지 않을 수 있습니다.

    awk 명령의 경우 시스템에서 추출 된 내장 파일은 '{print $ 1}'일 수 있습니다.

    연습에서 얻은 진정한 지식!

 

【종료】

1. 이것은 원본 기사이므로 저작권을 존중하십시오. 재 인쇄가 필요한 경우 전체 내용을 보관하고 출처를 표시하십시오. 편리한 경우 저에게 연락하여 확인하십시오.

2. 기사에 오류가 있거나 관련 내용에 대해 의견을 나누거나 논의하고 싶다면 언제든지 저에게 연락하십시오.

3. 이메일 : [email protected]

4. 공개 계정 : IOT 사물 인터넷 타운 

 

추천

출처blog.csdn.net/u012296253/article/details/106781754