본문 바로가기

Programming/Linux_Kernel

특정 시간 동안 system cpu 사용량 구하기 (linux)

오늘은 특정시간동안의 cpu 사용량 구하는 법에 대해서 알아보고자 합니다.

/proc/stat 정보를 조합하면 원하시는 정보를 얻으실 수 있습니다.

 cat /proc/stat

를 하시면 아래와 같은 정보를 얻을 수 있습니다.

# cat /proc/stat
cpu  4939 385 2406 38767 313 20 320 0 0
cpu0 4939 385 2406 38767 313 20 320 0 0
intr 102031 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 155 0 190 0 0 0 0 0 1045 0 8147 0 92 0 1286 0 0 0 0 0 0 0 0 2 0 0 0 133 0 0 0 1 0 0 0 1765 0 0 0 0 0 0 2 0 0 70437 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6020 0 0 0 0 2 0 10101 11 11 0 0 0 0 0 0 0 0 0 0 0 0 0 2382 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 39 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 198 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ctxt 145254
btime 1270915290
processes 1819
procs_running 3
procs_blocked 0

이중 우리에게 필요한 부분은

cpu  4939 385 2406 38767 313 20 320 0 0

입니다.

차래대로 다음 옵션들의 cpu 사용량의 누적 값입니다.
(2.6.29 kernel 기준입니다. 다른 버전들은
linux/fs/proc/stat.c
를 보면 쉽게 알 수 있습니다.)

user    nice    system    idle      iowait    irq    softirq    steal    guest

각 의미는 대략 다음과 같습니다.
(시간상 퍼왔습니다. 맞지 않는 부분은 kernel 버전 차이인듯 합니다.)

  • user : 사용자 영역 코드 실행 시간
  • system: 커널 영역 코드 실행 시간
  • nice : 기본보다 낮은 우선순위로 실행한 사용자 영역 코드 실행 시간
  • idle : I/O 완료가 아닌 대기 시간
  • wait : I/O 완료 대기 시간
  • hi : Hard Interrupt(IRQ)
  • si : Soft Interrupt(SoftIRQ)
  • zero : 끝


누적값이므로 일정시간의 간격을 두고 해당 값들을 얻어서 다음과 같이 계산하시면 됩니다.

cpu 사용백분율 = 100 - (idel의 차 * 100 / 모든 값들의 합)

< 예제 코드 - kernel 2.6.29 기준>

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>

#include <ctype.h>
#include <stddef.h>

#include <dirent.h>
#include <unistd.h>

#define STAT_FILE_NAME "/proc/stat"

typedef struct __str_cpu_info
{
 unsigned int user;
 unsigned int nice;
 unsigned int system;
 unsigned int idle;
 unsigned int iowait;
 unsigned int irq;
 unsigned int softirq;
 unsigned int steal;
 unsigned int guest;
}strCpuInfo;

int get_cpu_info(strCpuInfo* cpu_info)
{
 char filename[128];
 char line[1024];
 FILE *fp;
 int len;
 int ret=0;

 sprintf(filename, STAT_FILE_NAME);
 
 fp = fopen(filename, "r");
 if(fp == 0){
  printf("[CPU][ERROR] Can't open file %s\n", filename);
  return -1;
  }

 if(fgets(line, 1024, fp) == 0) {
  printf("[CPU][ERROR] fgets \n");
  return -1;
  }

 len = strlen(line);
 if(len < 1) {
  printf("[CPU][ERROR] len=%d \n", len);
  return -1;
  }
 line[--len] = 0;

 ret = sscanf(line, "%*s %u %u %u %u %u %u %u %u %u",
  &(cpu_info->user), &(cpu_info->nice), &(cpu_info->system), &(cpu_info->idle), &(cpu_info->iowait),
  &(cpu_info->irq ), &(cpu_info->softirq), &(cpu_info->steal), &(cpu_info->guest));

 if(ret!= 9)   {
  printf("[CPU][ERROR] sscanf return = %d\n", ret);
//  return -1;
     }
// printf("[CPU][DEBUG] %s\n", line);
 printf("[CPU][DEBUG] %u %u %u %u %u %u %u %u %u \n",
  cpu_info->user, cpu_info->nice, cpu_info->system, cpu_info->idle, cpu_info->iowait,
  cpu_info->irq, cpu_info->softirq, cpu_info->steal, cpu_info->guest);

 return 0;
 
}
 
int main(int argc, char *argv[])
{
 unsigned int delay_time = 1;
 strCpuInfo pre_cpu_info, after_cpu_info, calc_cpu_time;
 unsigned int cpu_persentage = 0;

 if(argc > 1){
  delay_time = atoi(argv[1]);
  printf("[CPU] delay_time = %d\n", delay_time);
  }
 
 
 get_cpu_info(&pre_cpu_info);
 sleep(delay_time);
 get_cpu_info(&after_cpu_info);

 calc_cpu_time.user  = after_cpu_info.user - pre_cpu_info.user;
 calc_cpu_time.nice  = after_cpu_info.nice - pre_cpu_info.nice;
 calc_cpu_time.system = after_cpu_info.system - pre_cpu_info.system;
 calc_cpu_time.idle  = after_cpu_info.idle - pre_cpu_info.idle;
 calc_cpu_time.iowait  = after_cpu_info.iowait - pre_cpu_info.iowait;
 calc_cpu_time.irq  = after_cpu_info.irq  - pre_cpu_info.irq ;
 calc_cpu_time.softirq = after_cpu_info.softirq - pre_cpu_info.softirq;
 calc_cpu_time.steal  = after_cpu_info.steal - pre_cpu_info.steal;
 calc_cpu_time.guest  = after_cpu_info.guest - pre_cpu_info.guest;

 
 cpu_persentage = calc_cpu_time.idle*100/(calc_cpu_time.user + calc_cpu_time.nice + calc_cpu_time.system +
  calc_cpu_time.idle + calc_cpu_time.iowait + calc_cpu_time.irq +
  calc_cpu_time.softirq + calc_cpu_time.steal + calc_cpu_time.guest);

 
 printf("[CPU][DEBUG] %u %u %u %u %u %u %u %u %u \n",
   calc_cpu_time.user, calc_cpu_time.nice, calc_cpu_time.system, calc_cpu_time.idle, calc_cpu_time.iowait,
   calc_cpu_time.irq, calc_cpu_time.softirq, calc_cpu_time.steal, calc_cpu_time.guest);

 printf("[CPU] cpu persentage = %u%% \n", 100 - cpu_persentage);
 
 return 0;
}