C에서 Linux에서 PID로 프로세스의 CPU 사용량을 계산하는 방법은 무엇입니까?


94

Linux에서 주어진 프로세스 ID에 대해 프로그래밍 방식으로 [C에서] CPU 사용량 %를 계산하고 싶습니다.

주어진 프로세스에 대한 실시간 CPU 사용량 %를 어떻게 얻을 수 있습니까?

더 명확하게하려면 :

  • 제공된 프로세스 ID 또는 프로세스에 대한 CPU 사용량을 확인할 수 있어야합니다.
  • 프로세스가 하위 프로세스 일 필요는 없습니다.
  • 'C'언어로 된 솔루션을 원합니다.

top의 출력을 잡는 (grep-ing) 어떨까요?
dusoft


'top'을 시작하려면 "비싼"시스템 호출이 필요할 것입니다.
Liran Orevi

@Liran : 바르게 말했다 :
vpram86

이런 일을하는 방법은 잊어 버리세요 .... in C
codingfreak

답변:


148

에서 데이터를 구문 분석해야합니다 /proc/<PID>/stat. 다음은 Documentation/filesystems/proc.txt커널 소스 의 처음 몇 개 필드입니다 .

Table 1-3: Contents of the stat files (as of 2.6.22-rc3)
..............................................................................
 Field          Content
  pid           process id
  tcomm         filename of the executable
  state         state (R is running, S is sleeping, D is sleeping in an
                uninterruptible wait, Z is zombie, T is traced or stopped)
  ppid          process id of the parent process
  pgrp          pgrp of the process
  sid           session id
  tty_nr        tty the process uses
  tty_pgrp      pgrp of the tty
  flags         task flags
  min_flt       number of minor faults
  cmin_flt      number of minor faults with child's
  maj_flt       number of major faults
  cmaj_flt      number of major faults with child's
  utime         user mode jiffies
  stime         kernel mode jiffies
  cutime        user mode jiffies with child's
  cstime        kernel mode jiffies with child's

아마도 utime및 / 또는 stime. 또한 다음과 같은 cpu에서 행 을 읽어야합니다 /proc/stat.

cpu  192369 7119 480152 122044337 14142 9937 26747 0 0

다양한 카테고리에서 사용 된 누적 CPU 시간을 jiffies 단위로 알려줍니다. time_total측정 값 을 얻으려면이 선에있는 값의 합계를 얻어야합니다 .

관심있는 프로세스 utimestime에서 모두 읽고 time_total에서 읽 습니다 /proc/stat. 그런 다음 1 초 정도 자고 모두 다시 읽으십시오. 이제 다음을 사용하여 샘플링 시간 동안 프로세스의 CPU 사용량을 계산할 수 있습니다.

user_util = 100 * (utime_after - utime_before) / (time_total_after - time_total_before);
sys_util = 100 * (stime_after - stime_before) / (time_total_after - time_total_before);

말이 되나?


11
"jiffy"는 CPU 시간의 단위입니다. 벽시계 시간에 정확히 일치하는 것은 아키텍처와 커널 구성 방식에 따라 다르지만 중요한 것은 /proc/statCPU가 총 /proc/<PID>/stat실행 한 jiff의 수를 알려주고 a에 의해 실행 된 jiff의 수를 알려주는 것입니다. 단일 프로세스.
caf

1
@advocate : 커널에서 프로세스 실행 통계를 검색하는 인터페이스를 구현하는 의사 파일입니다.
caf

4
필드에 대한 자세한 내용은 추구하는 사람들에게 : man proc당신의 친구 (검색입니다 /proc/[pid]/stat)
redShadow

1
caf의 솔루션과 zizzu (아래)에서 제공하는 솔루션을 비교하면 caf의 솔루션은 시스템 및 사용자 시간을 별도로 제공하지만이 값 중 어느 것도 CPU 수와 곱하지 않습니다. 그렇게해야하지 않습니까?
linuxfan

2
분명히 OP는 동의하지 않았습니다. 여기서 중요한 통찰력은 사용하는 /proc가상 파일 시스템 : 같은 표준 C 파일 시스템 액세스 기능의 가르침을 fopen()scanf()지점 옆에있다.
caf

11

getrusage () 는 현재 프로세스 또는 하위 프로세스의 사용을 결정하는 데 도움이 될 수 있습니다.

업데이트 : API가 기억 나지 않습니다. 그러나 모든 세부 사항은 / proc / PID / stat에 있으므로 파싱 할 수 있다면 백분율을 얻을 수 있습니다.

편집 : CPU %는 계산하기가 쉽지 않기 때문에 여기에서 샘플링 종류를 사용할 수 있습니다. 특정 시점에서 PID에 대한 ctime 및 utime을 읽고 1 초 후에 동일한 값을 다시 읽습니다. 차이를 찾아서 백으로 나눕니다. 지난 1 초 동안 해당 프로세스에 대한 활용도를 얻을 수 있습니다.

(프로세서가 많으면 더 복잡해질 수 있음)


2
getrusage () 시스템 호출이 프로세스의 CPU 사용량을 계산하는 데 어떻게 도움이됩니까?
codingfreak

@codingfreak. 나는 질문을 오해했다. 이제 업데이트 한 후 삭제합니다.
vpram86

1
@Aviator CPU % = (processusertime + processkerneltime) / (CPUusertime + CPUkerneltime) "processusertime"등에 대한 값을 어떻게 얻을 수 있습니까? ??? "/ proc / PID / stat"파일에 다른 값이 있습니다. 그래서 어느 것이 어떤 값에 해당합니까?
codingfreak

@codingfreak : CPU 시간은 계산하기 어렵습니다. 모든 PID를 통해 루프 U 필요 내가 (확실하지 불구하고) 추측 통계
vpram86

@Aviator는 그것을 할 수있는 방법이나 다른 방법이있을 것입니다 ... top과 같은 응용 프로그램도 출력에 표시 할 CPU 사용량을 계산해야하기 때문입니다
codingfreak

6

나 같은 초보자를위한 쉬운 단계 :

  1. /proc/stat를 얻으려면 의 첫 번째 줄을 읽으십시오 total_cpu_usage1.
    sscanf(line,"%*s %llu %llu %llu %llu",&user,&nice,&system,&idle);
    total_cpu_usage1 = user + nice + system + idle;
  1. 다음 과 같이 CPU 사용량을 알고 싶은 프로세스의 PID가 /proc/pid/stat어디에 있는지 읽으십시오 pid.
    sscanf(line,
    "%*d %*s %*c %*d" //pid,command,state,ppid

    "%*d %*d %*d %*d %*u %*lu %*lu %*lu %*lu"

    "%lu %lu" //usertime,systemtime

    "%*ld %*ld %*ld %*ld %*ld %*ld %*llu"

    "%*lu", //virtual memory size in bytes
    ....)
  1. 이제 요약 usertimesystemtime및 GETproc_times1
  2. 이제 1 초 이상 기다려
  3. 다시하고 total_cpu_usage2,proc_times2

공식은 다음과 같습니다.

(number of processors) * (proc_times2 - proc_times1) * 100 / (float) (total_cpu_usage2 - total_cpu_usage1)

에서 CPU의 양을 얻을 수 있습니다 /proc/cpuinfo.


2
귀하의 솔루션은 좋지만 CPU 수를 얻으려면 더 간단하게 만드십시오. 이 사람을 포함 #include <unistd.h>,이 메서드를 호출int nb = sysconf(_SC_NPROCESSORS_ONLN);
데이비드 귀용

1
delta (proc_times)가 실행 된 코어에 대한 것이라고 가정하고 (프로세서 수)를 곱하는 이유를 이해하지 못합니다. 요인 또는 CPU를 곱하지 않으면 정확해야합니다.
JayabalanAaron 2011

5

프로세스의 user + kernel cpu 사용량을 계산하기 위해 cafs 답변을 기반으로 두 개의 작은 C 함수를 작성했습니다. https://github.com/fho/code_snippets/blob/master/c/getusage.c


컴파일하는 동안 오류가 발생하고 어떻게 사용할 수 있습니까?
Medhat 2014

나는 main () 함수가 없으므로 컴파일하고 실행할 수있는 "독립 실행 형"프로그램이 아닙니다. getusage.c의 함수로 몇 가지 작업을 수행하는 main () 함수를 작성해야합니다.
fho

실제로 C 함수를 사용하지 않습니다. 임의의 언어를 사용하여 명령 출력을 구문 분석합니다.
Graham

4

자세한 내용 은 proc에 대한 맨 페이지를 읽을 수 있지만 요약하면 / proc / [number] / stat를 읽고 프로세스에 대한 정보를 얻을 수 있습니다. 이것은 'ps'명령에서도 사용됩니다.

모든 필드와 scanf 형식 지정자는 proc manpag e에 문서화되어 있습니다.

다음은 맨 페이지에서 복사 한 정보 중 일부입니다 (매우 깁니다).

          pid %d The process ID.

          comm %s
                 The  filename of the executable, in parentheses.  This is
                 visible whether or not the executable is swapped out.

          state %c
                 One character from the string "RSDZTW" where  R  is  runâ
                 ning,  S is sleeping in an interruptible wait, D is waitâ
                 ing in uninterruptible disk sleep,  Z  is  zombie,  T  is
                 traced or stopped (on a signal), and W is paging.

          ppid %d
                 The PID of the parent.

          pgrp %d
                 The process group ID of the process.

          session %d
                 The session ID of the process.

          tty_nr %d
                 The tty the process uses.

          tpgid %d
                 The  process group ID of the process which currently owns
                 the tty that the process is connected to.

“CPU 사용량”과“현재 상태”는 위치 및 속도와 같습니다. 하나를 안다면 다른 하나를 알 수 없습니다. CPU 사용량은 기간에 따라 달라 지므로 프로세스가 "R"상태에있는 빈도를 직접 확인해야합니다.
Bombe

흠, 좋은 질문입니다. 나는 항상 그것이있을 것이라고 생각했습니다! 아마도 당신은 이러한 변수에서 그것을 계산할 수 있어야한다
안드레 밀러

당신은 당신이 CPU 사용량을 볼 수 있습니다 top 명령의 출력을 확인 ....하지만 계산의 CPU 사용량에 최고 출력을 통해 greping에 intrested하는 있지 않다 경우 .....
codingfreak

@codingfreak : ps aux더 낫다 :)
vpram86

@Aviator-CPU 사용량 %를 결정하기 위해 쉘 명령의 출력을 잊으라고 이미 U에게 말했습니다.
codingfreak

2

"pidstat"명령을 살펴보면 정확히 필요한 것처럼 들립니다.


@James-FEDORA 9 컴퓨터에서 pidstat 명령에 액세스 할 수 없습니다.
codingfreak

@codingfreak-Sysstat 도구를 설치해야합니다
Chintan Parikh

2

이것은 내 해결책입니다 ...

/*
this program is looking for CPU,Memory,Procs also u can look glibtop header there was a lot of usefull function have fun..
systeminfo.c
*/
#include <stdio.h>
#include <glibtop.h>
#include <glibtop/cpu.h>
#include <glibtop/mem.h>
#include <glibtop/proclist.h>



int main(){

glibtop_init();

glibtop_cpu cpu;
glibtop_mem memory;
glibtop_proclist proclist;

glibtop_get_cpu (&cpu);
glibtop_get_mem(&memory);


printf("CPU TYPE INFORMATIONS \n\n"
"Cpu Total : %ld \n"
"Cpu User : %ld \n"
"Cpu Nice : %ld \n"
"Cpu Sys : %ld \n"
"Cpu Idle : %ld \n"
"Cpu Frequences : %ld \n",
(unsigned long)cpu.total,
(unsigned long)cpu.user,
(unsigned long)cpu.nice,
(unsigned long)cpu.sys,
(unsigned long)cpu.idle,
(unsigned long)cpu.frequency);

printf("\nMEMORY USING\n\n"
"Memory Total : %ld MB\n"
"Memory Used : %ld MB\n"
"Memory Free : %ld MB\n"
"Memory Buffered : %ld MB\n"
"Memory Cached : %ld MB\n"
"Memory user : %ld MB\n"
"Memory Locked : %ld MB\n",
(unsigned long)memory.total/(1024*1024),
(unsigned long)memory.used/(1024*1024),
(unsigned long)memory.free/(1024*1024),
(unsigned long)memory.shared/(1024*1024),
(unsigned long)memory.buffer/(1024*1024),
(unsigned long)memory.cached/(1024*1024),
(unsigned long)memory.user/(1024*1024),
(unsigned long)memory.locked/(1024*1024));

int which,arg;
glibtop_get_proclist(&proclist,which,arg);
printf("%ld\n%ld\n%ld\n",
(unsigned long)proclist.number,
(unsigned long)proclist.total,
(unsigned long)proclist.size);
return 0;
}

makefile is
CC=gcc
CFLAGS=-Wall -g
CLIBS=-lgtop-2.0 -lgtop_sysdeps-2.0 -lgtop_common-2.0

cpuinfo:cpu.c
$(CC) $(CFLAGS) systeminfo.c -o systeminfo $(CLIBS)
clean:
rm -f systeminfo

1
libgtop 라이브러리의 도움을 사용하는 것 같습니다 ..?
codingfreak 11

1
나는 이것을 좋아한다-도서관은 간단하다. 총 사용량이 총 용량의 몇 %인지 확인하는 방법이 있는지 궁금합니다.
세라

1

특정 프로세스를 모니터링하려는 경우 일반적으로 스크립팅으로 수행됩니다. 다음은 펄의 예입니다. 이것은 top과 같은 방식으로 퍼센트를 넣어 하나의 CPU에 scalling합니다. 그런 다음 일부 프로세스가 2 개의 스레드로 작업 중일 때 CPU 사용량이 100 % 이상이 될 수 있습니다. 특히 cpu 코어가 계산되는 방식을 살펴보십시오. D 다음 예제를 보여 드리겠습니다.

#!/usr/bin/perl

my $pid=1234; #insert here monitored process PID

#returns current process time counters or single undef if unavailable
#returns:  1. process counter  , 2. system counter , 3. total system cpu cores
sub GetCurrentLoads {
    my $pid=shift;
    my $fh;
    my $line;
    open $fh,'<',"/proc/$pid/stat" or return undef;
    $line=<$fh>;
    close $fh;
    return undef unless $line=~/^\d+ \([^)]+\) \S \d+ \d+ \d+ \d+ -?\d+ \d+ \d+ \d+ \d+ \d+ (\d+) (\d+)/;
    my $TimeApp=$1+$2;
    my $TimeSystem=0;
    my $CpuCount=0;
    open $fh,'<',"/proc/stat" or return undef;
    while (defined($line=<$fh>)) {
        if ($line=~/^cpu\s/) {
            foreach my $nr ($line=~/\d+/g) { $TimeSystem+=$nr; };
            next;
        };
        $CpuCount++ if $line=~/^cpu\d/;
    }
    close $fh;
    return undef if $TimeSystem==0;
    return $TimeApp,$TimeSystem,$CpuCount;
}

my ($currApp,$currSys,$lastApp,$lastSys,$cores);
while () {
    ($currApp,$currSys,$cores)=GetCurrentLoads($pid);
    printf "Load is: %5.1f\%\n",($currApp-$lastApp)/($currSys-$lastSys)*$cores*100 if defined $currApp and defined $lastApp and defined $currSys and defined $lastSys;
    ($lastApp,$lastSys)=($currApp,$currSys);
    sleep 1;
}

모든 모니터링에 도움이되기를 바랍니다. 물론 내가 사용한 펄 정규식을 C 소스로 변환하려면 scanf 또는 다른 C 함수를 사용해야합니다. 물론 수면 1 초는 필수는 아닙니다. 언제든지 사용할 수 있습니다. 효과는 지정된 기간에 평균 부하를 받게됩니다. 모니터링에 사용할 때 물론 마지막 값은 외부에 넣어야합니다. 모니터링은 보통 주기적으로 스크립트를 호출하고 스크립트는 최대한 빨리 작업을 완료해야하기 때문에 필요합니다.


0

설치 psacct또는 acct패키지. 그런 다음 sa명령을 사용하여 다양한 명령에 사용 된 CPU 시간을 표시합니다. sa man 페이지

nixCraft 사이트 의 멋진 하우투 .


0

GNU "시간"명령 소스 코드를 살펴볼 가치가 있다고 생각합니다. time 실제 경과 시간과 함께 사용자 / 시스템 CPU 시간을 출력합니다. wait3 / wait4 시스템 호출 (사용 가능한 경우)을 호출하고 그렇지 않으면 시간 시스템 호출을 호출합니다. wait * 시스템 호출은 "rusage"구조체 변수를 반환하고 시간 시스템 호출은 "tms"를 반환합니다. 또한 매우 흥미로운 타이밍 정보를 반환하는 getrusage 시스템 호출을 살펴볼 수 있습니다. 시각


GNU "시간"은 "시간"의 자식 프로세스입니다
그레이엄

0

proc에서 이것을 구문 분석하는 대신 getrusage () 또는 clock_gettime ()과 같은 함수를 사용하여 CPU 사용량을 비율 또는 wallclock 시간 및 CPU에서 사용 된 프로세스 / 스레드 시간으로 계산할 수 있습니다.


getrusage clock_gettime은 모든 프로세스가 아닌 제한적입니다
Graham

0

strace를 사용하여 CPU 사용량을 기간별로 계산해야합니다.

# top -b -n 1 -p 3889
top - 16:46:37 up  1:04,  3 users,  load average: 0.00, 0.01, 0.02
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  5594496 total,  5158284 free,   232132 used,   204080 buff/cache
KiB Swap:  3309564 total,  3309564 free,        0 used.  5113756 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 3889 root      20   0  162016   2220   1544 S   0.0  0.0   0:05.77 top
# strace top -b -n 1 -p 3889
.
.
.
stat("/proc/3889", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
open("/proc/3889/stat", O_RDONLY)       = 7
read(7, "3889 (top) S 3854 3889 3854 3481"..., 1024) = 342
.
.
.

nanosleep({0, 150000000}, NULL)         = 0
.
.
.
stat("/proc/3889", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
open("/proc/3889/stat", O_RDONLY)       = 7
read(7, "3889 (top) S 3854 3889 3854 3481"..., 1024) = 342
.
.
.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.