기존 Memory 사용률을 스크립트 파일로 작성했지만 C 코드에서 구현 가능하게 수정
proc/meminfo에 있는 MemTotal의 정보와 MemFree의 정보를 grep 하여 문자열로 가지고 온다. 그러고 나서 하나씩 그 단어에 맞게 가져온 뒤에 각각 변수에 저장해주는데 my_atoi라는 문자열을 정수로 바꿔주는 함수를 만들어 정수로 변환해준다.
입력된 문자열을 for문을 통해 문자하나하나 탐색하게 해 주고 모든 문자열을 검색 다한 NULL을 만났을 때 for문을 종료한다. 문자열에 '0'을 빼게 되면 진짜 숫자가 구해진다. 구한 정수를 반환하는 알고리즘이다.
시스템의 메모리 사용량을 구하는 방법은 MemTotal-MemFree/MemTotal이기에 계산을 하여 넣어주고 리붓을 진행하게 된다.
SW 동작 설정을 위한 User I/F를 제공하기위한 조건
A. 모니터링 주기
B. 로그 파일 위치
C. 프로세스 중단 상태 감지 시 Reboot 복구 동작 수행/미수행 관련 플래그
D. CPU사용량, 메모리 사용량 2개에 대한 임계 값
config 파일
SW동작을 위한 설정값들을 conf파일에 저장
LOGPATH => 어디에 저장할건지 경로를 나타낸다.
Configcycle => 몇초에 한 번씩 주기를 설정해 검사를 반복할 건지에 대한 설정값이다.
REBOOT => 리붓할건지 안 할 건지에 대한 설정값이다.
CPUthreshold => CPU사용량의 대한 임계값을 얼마나 할 건지 설정값이다.
Memorythreshold=> Memory 사용량의 대한 임계값을 얼마나 할 건지 설정값이다.
-> 이제 설정한 config파일을 읽어 C언어 코드에 변수에 저장해 넣어야 한다.
문자열을 각각 confName에 conf이름을, confuse에는 사용량을 저장한다. confuse를 문자열로 저장하는 이유는 경로가 문자열이기 때문이다.
문자열에 맞게 정수로 변환 뒤 int 정수형 변수에 저장하여 임계값을 실행할 수 있게 한다.
최종 결과
Linux화면에서 Log기록 파일에 10초 간격으로 출력되는 것을 확인할 수 있다.
CPU는 100 Memory는 50으로 출력 화면에서도 임계값에 대해 출력한 걸 확인할 수 있다.
CPU의 임계값을 1로 해보고 reboot 시켰을 때 reboot 한 시간과 기록 그리고 초과한 CPU의 ppid도 출력되는 것을 확인할 수 있다. (보드 기준의 코딩이라 리눅스의 결과와 다릅니다 밑에 보드 기록 보여드리겠습니다.)
4G LTE Board
Reboot 실험을 위해 reboot을 하게 하였고 memory 임계값을 1로 만들어 reboot 하게 실행
memory의 사용량이 넘어 Reboot 진행한 것을 확인할 수 있다.
C언어 Code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#define file_name "cpuconfigu.conf"
const char *CPUSTAT = "/proc/stat"; // cpu 정보
const char *MEMINFO = "/proc/meminfo"; // mem 정보
int my_atoi(const char* str) {
int ret = 0;
int i;
for (i = 0; str[i] != '\0'; i++) //NULL문자만나면 for문 종료
ret = ret * 10 + (str[i] - '0'); //숫자 문자에 '0'을 빼면 레알 숫자가 구해짐
return ret;
}
typedef struct cpumemoryconf {
char confName[100];
char confuse[100];
} femto_info;
// CPU 정보
typedef struct _cpuinfo
{
FILE *fp; // 파일 스트림 포인터
char cpuname[50]; //1) cpu : cpu 구분
long long cpu_user; //2) user : 사용자 영역 코드 실행 시간
long long cpu_nice; //3) system: 커널 영역 코드 실행 시간
long long cpu_system; //4) nice : 기본보다 낮은 우선순위로 실행한 사용자 영역 코드 실행 시간
long long cpu_idle; //5) idle : 대기 시간
long long cpu_wait; //6) wait : I/O 완료 대기 시간
long long cpu_hi; //7) hi : Hard Interrupt(IRQ)
long long cpu_si; //8) si : Soft Interrupt(SoftIRQ)
long long cpu_zero; //9) zero : 끝
} CPU_P;
// MEM 정보
typedef struct _meminfo
{
FILE *fp; // 파일 스트림 포인터
char memname[50]; // MEM 구분
long long mem_total; // MEM total
long long mem_info;
} MEM_P;
CPU_P *cpu_dfopen()
{
CPU_P *CP;
// /proc/stat 파일을 연다.
CP = (CPU_P *)malloc(sizeof(CPU_P));
if(!(CP->fp = fopen(CPUSTAT, "r")) )
{
return NULL;
}
else
return CP;
}
MEM_P *mem_dfopen()
{
MEM_P *MP;
// /proc/meminfo 파일을 연다.
MP = (MEM_P *)malloc(sizeof(MEM_P));
if(!(MP->fp = fopen(MEMINFO, "r") ))
{
return NULL;
}
else
return MP;
}
CPU_P *cpu_dfget(CPU_P *CP)
{
char c_buf[1024];
// /proc/stat 으로 부터 CPU 정보를 얻어온다.
while(fgets(c_buf, 1024, CP->fp))
{
sscanf(c_buf, "%s",CP->cpuname);
if (strncmp(CP->cpuname,"cpu",3) == 0)
{
// CPU 시스템의 현재 사용량을 구한다.
sscanf(c_buf, "%s %llu %llu %llu %llu %llu %llu %llu %llu",CP->cpuname, &CP->cpu_user, &CP->cpu_nice, &CP->cpu_system, &CP->cpu_idle, &CP->cpu_wait, &CP->cpu_hi, &CP->cpu_si, &CP->cpu_zero);
return CP;
}
}
rewind(CP->fp);
return NULL;
}
MEM_P *mem_dfget(MEM_P *MP)
{
char m_buf[1024];
// /proc/meminfo 으로 부터 MEM 정보를 얻어온다.
while(fgets(m_buf, 1024, MP->fp))
{
// MEM 항목중 필요한 항목만 추출한다.
sscanf(m_buf, "%s",MP->memname);
if (!strcmp(MP->memname,"MemTotal:")|| !strcmp( MP->memname,"MemFree:")|| !strcmp( MP->memname ,"Buffers:")|| !strcmp( MP->memname , "Cached:" )|| !strcmp( MP->memname , "SwapCached:" )|| !strcmp( MP->memname ,"SwapTotal:" )|| !strcmp( MP->memname ,"SwapFree:" )){
// MEM 시스템의 현재 사용량을 구한다.
sscanf(m_buf, "%s %llu " ,MP->memname, &MP->mem_info);
return MP;
}
}
rewind(MP->fp);
return NULL;
}
int dfclose(CPU_P *CP, MEM_P *MP)
{
fclose(CP->fp);
fclose(MP->fp);
}
int main(int argc, char **argv)
{
femto_info femtos[100];
FILE* fp = fopen(file_name, "r");
CPU_P *CP;
MEM_P *MP;
printf("\n================[ NAME ]===================" );
printf("\nQUCELL NETWORKS\nManagement SW Team\nIntern\nSaehyeong.woo\n+82 10-4064-0659\nindividual Project\n");
if ((CP=cpu_dfopen()) == NULL || (MP=mem_dfopen()) == NULL ) {
perror("error");
return 1;
}
if (fp == NULL) {
printf("fail to read file");
return 0;
}
char buffer[1001],*token;
int i = 0;
int idx = 0;
while (!feof(fp)) {
i = 0;
fgets(buffer, 1001, fp); //ex
token = strtok(buffer, "=");
while (token != NULL) {
if (i == 0) {
strcpy(femtos[idx].confName, token);
}
else if (i == 1) {
strcpy(femtos[idx].confuse, token);
}
i++;
token = strtok(NULL, " ");
}
idx++;
}
printf("\n==========[ cpuconfigu.conf VALUE ]========== \n" );
for (int i = 0; i < idx; i++) {
printf("[%d]%s %s\n", i,femtos[i].confName, femtos[i].confuse);
}
system(femtos[1].confuse); //road
int ni = my_atoi(femtos[4].confuse);
int rbt = my_atoi(femtos[7].confuse);
int cpt = my_atoi(femtos[10].confuse);
int memt = my_atoi(femtos[11].confuse);
fclose(fp); // 파일 닫기
while(1)
{
printf("\n================[ CPU INFO ]================ \n" );
time_t timer;
struct tm *t;
char date[32]={0,};
timer = time(NULL);
t = localtime(&timer);
sprintf(date, "%04d-%02d-%02d", t->tm_year +1900, t->tm_mon+1, t->tm_mday);
printf ("date: %s\n", date);
sprintf(date, "%02d:%02d:%02d", t->tm_hour, t->tm_min, t->tm_sec);
printf ("time: %s\n", date);
float cputTotal = 0;
FILE* fp = fopen("LOG.log","a");
fprintf(fp,"\n================[ CPU INFO ]================\n Date: %04d-%02d-%02d Time:%02d:%02d:%02d \n\n" ,t->tm_year +1900, t->tm_mon+1, t->tm_mday,t->tm_hour, t->tm_min, t->tm_sec);
fclose(fp);
while(cpu_dfget(CP))
{
// 모든 정보 보기
printf("%-10s %10llu %10llu %10llu %10llu %10llu %10llu %10llu " , CP->cpuname, CP->cpu_user, CP->cpu_nice, CP->cpu_system, CP->cpu_idle, CP->cpu_wait, CP->cpu_hi, CP->cpu_si );
// CPU사용량 정보 보기
float CPUusage = (float)(CP->cpu_user + CP->cpu_nice + CP->cpu_system) / (CP->cpu_user + CP->cpu_nice + CP->cpu_system + CP->cpu_idle) * 100 ;
printf(", Usage: %10.2f %% \n" , CPUusage);
cputTotal += CPUusage;
FILE* fp = fopen("LOG.log","a");
fprintf(fp," %-10s => Usage:%10.2f % \n cputTotal: %10.2f \n\n" ,CP->cpuname ,CPUusage,cputTotal);
fclose(fp);
printf("Total Usage: %10.2f %% \n" , cputTotal);
float cpuUsageAvrage = cputTotal/3.0;
printf("CPU Usage Average: %10.2f %% \n",cpuUsageAvrage);
if(cputTotal>cpt){
if(1==rbt){
FILE *sp = fopen("LOG.log","a");
fprintf(sp,"\n---------SHUT DOWN CPU Over %d percent.-----------\nShutdown CPU%10.2f %% \n",cpt,cputTotal);
system("top -b | head -n 129 > x.log");
system("sed -n '4p' x.log > topinfo.log");
system("sed -e '1,4d' x.log > xx.log");
system("sort -k7 -r xx.log > xxx.log");
system("head -n 1 xxx.log > xxxx.log");
system("cat topinfo.log xxxx.log >> LOG.log");
system("rm topinfo.log");
system("rm x.log");
system("rm xx.log");
system("rm xxx.log");
system("rm xxxx.log");
fclose(sp);
system("reboot");
}
else{
printf("It's dangerous because your CPU is over %d%. \n\n",cpt);
}
}
else{
printf("It is safe as CPU is below %d. \n\n",cpt);
}
}
FILE *np,*up,*op = NULL;
op=fopen("LOG.log","a");
printf("===============[ MEMORY INFO ]============== \n" );
fprintf(op,"================[ MEMROY INFO ]================\n Date: %04d-%02d-%02d Time:%02d:%02d:%02d \n\n" ,t->tm_year +1900, t->tm_mon+1, t->tm_mday,t->tm_hour, t->tm_min, t->tm_sec);
fclose(op);
while(mem_dfget(MP))
{
FILE* fp = fopen("LOG.log","a");
printf("%-15s %10llu KB \n" , MP->memname, MP->mem_info);
fprintf(fp,"%-15s %10llu KB \n\n" , MP->memname, MP->mem_info);
fclose(fp);
}
op=fopen("LOG.log","a");
printf("\n===============[ MEMORY CAL USAGE ]============== \n" );
fprintf(op,"================[ MEMROY NOW USAGE ]================\n Date: %04d-%02d-%02d Time:%02d:%02d:%02d \n\n" ,t->tm_year +1900, t->tm_mon+1, t->tm_mday,t->tm_hour, t->tm_min, t->tm_sec);
fclose(op);
char line[10240];
char line2[10240];
if((np = popen("grep MemTotal /proc/meminfo | awk '{print $2}'", "r")) && (up = popen("grep MemFree /proc/meminfo | awk '{print $2}'", "r")) == NULL ) {
return 1;
}
/* ls -al 명령어로 출력하는 내용을 한줄씩 읽어서 처리하는 함 */
while(fgets(line, 10240, np) && fgets(line2, 10240, up) != NULL ) {
int str = my_atoi(line);
int str2 = my_atoi(line2);
float str3 = str-str2;
float str4 = (float)str3/(float)str;
printf("Memory Usage: %.2f %",str4*100);
op=fopen("LOG.log","a");
fprintf(op,"Memory Usage: %.2f% \n",str4*100);
fclose(op);
if(str4*100>memt){
if(1==rbt){
FILE *sp = fopen("LOG.log","a");
fprintf(sp,"\n---------SHUT DOWN MEMORY Over %d percent.-----------\nShutdown Memory Usage%10.2f %% \n",memt,cputTotal);
system("top -b | head -n 129 > x.log");
system("sed -n '4p' x.log > topinfo.log");
system("sed -e '1,4d' x.log > xx.log");
system("sort -k6 -r xx.log > xxx.log");
system("head -n 1 xxx.log > xxxx.log");
system("cat topinfo.log xxxx.log >> LOG.log");
system("rm topinfo.log");
system("rm x.log");
system("rm xx.log");
system("rm xxx.log");
system("rm xxxx.log");
fclose(sp);
system("reboot");
}
else{
printf("\nMemory is over %d% And needs cleaning.\n",memt);
}
}
else{
printf("\nIt is safe as the memory is less than %d \n",memt);
}
}
op=fopen("LOG.log","a");
fprintf(op,"\n================[ CPU TOP 10 ]================\n Date: %04d-%02d-%02d Time:%02d:%02d:%02d \n\n" ,t->tm_year +1900, t->tm_mon+1, t->tm_mday,t->tm_hour, t->tm_min, t->tm_sec);
fclose(op);
printf("\n===============[ CPU TOP 10 ]============== \n" );
system("top -b | head -n 129 > x.log");
system("sed -n '1,4p' x.log > topinfo.log");
system("sed -e '1,4d' x.log > xx.log");
system("sort -k7 -r xx.log > xxx.log");
system("head -n 10 xxx.log > xxxx.log");
system("cat topinfo.log xxxx.log");
system("cat topinfo.log xxxx.log >> LOG.log");
//system("top -b | head -n 70 | sort -k7 >> CPU_TOP_7.log");
//system("tail CPU_TOP_7.log");
op=fopen("LOG.log","a");
fprintf(op,"\n================[ MEMROY TOP 10 ]================\n Date: %04d-%02d-%02d Time:%02d:%02d:%02d \n\n" ,t->tm_year +1900, t->tm_mon+1, t->tm_mday,t->tm_hour, t->tm_min, t->tm_sec);
fclose(op);
printf("\n===============[ MEMORY TOP 10 ]============== \n" );
system("top -b | head -n 129 > x.log");
system("sed -n '1,4p' x.log > topinfo.log");
system("sed -e '1,4d' x.log > xx.log");
system("sort -k6 -r xx.log > xxx.log");
system("head -n 10 xxx.log > xxxx.log");
system("cat topinfo.log xxxx.log");
system("cat topinfo.log xxxx.log >> LOG.log");
system("rm topinfo.log");
system("rm x.log");
system("rm xx.log");
system("rm xxx.log");
system("rm xxxx.log");
//system("date >> MEMORY_TOP_7.log");
//system("top -b | head -n 70 | sort -k6 >> MEMORY_TOP_7.log");
//system("tail MEMORY_TOP_7.log");
printf(" \n");
printf(" \n");
printf(" \n");
pclose(np);
pclose(up);
usleep(ni*1000000);
}
return 0;
}
Config code
[Device Log]
LOGPATH ="cd"
[Monitoring Cycle]
Configcycle =10
[Reboot Yes(1) or No(0)]
REBOOT =1
[Cpu or Memroy USE Value]
CPUthreshold =1
Memorythreshold =50
'C 언어' 카테고리의 다른 글
C Language Configure File 문자열 행 상관없이 읽는 문제 해결 (0) | 2022.07.28 |
---|---|
C Language Configure File Path Move Problem Resolution (0) | 2022.07.25 |
C Language : 리눅스와 4G Board에서 CPU,MEM process를 OAM하여 출력하는 코드 및 관리 (0) | 2022.07.14 |
Tera Term <--> WinSCP <--> Linux Connect (0) | 2022.07.14 |
C CodingTest Practice (약수의 개수와 덧셈) (0) | 2022.07.08 |