developer tip

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

copycodes 2020. 8. 30. 08:50
반응형

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


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

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

더 명확하게하려면 :

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

에서 데이터를 구문 분석해야합니다 /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);

말이 되나?


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

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

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

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


나 같은 너브를위한 쉬운 단계 :)

total_cpu_usage1을 얻으려면 / proc / stat의 첫 번째 줄을 읽으십시오.

sscanf(line,"%*s %llu %llu %llu %llu",&user,&nice,&system,&idle);
total_cpu_usage1 = user + nice + system + idle;

/ proc / pid / stat를 읽으십시오. 여기서 pid는 다음과 같이 CPU 사용량을 알고 자하는 프로세스의 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
....)

이제 사용자 시간과 시스템 시간을 합하고 proc_times1을 얻습니다.

이제 1 초 이상 기다려

다시하고 total_cpu_usage2 및 proc_times2를 얻으십시오.

공식은 다음과 같습니다.

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

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


I wrote two little C function based on cafs answer to calculate the user+kernel cpu usage of of an process: https://github.com/fho/code_snippets/blob/master/c/getusage.c


You can read the manpage for proc for more detail, but in summary you can read /proc/[number]/stat to get the information about a process. This is also used by the 'ps' command.

All the fields and their scanf format specifiers are documented in the proc manpage.

Here are some of the information from the manpage copied (it is quite long):

          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.

Take a look at the "pidstat" command, sounds like exactly what you require.


This is my solution...

/*
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

When you want monitor specified process, usually it is done by scripting. Here is perl example. This put percents as the same way as top, scalling it to one CPU. Then when some process is active working with 2 threads, cpu usage can be more than 100%. Specially look how cpu cores are counted :D then let me show my example:

#!/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;
}

I hope it will help you in any monitoring. Of course you should use scanf or other C functions for converting any perl regexpes I've used to C source. Of course 1 second for sleeping is not mandatory. you can use any time. effect is, you will get averrage load on specfied time period. When you will use it for monitoring, of course last values you should put outside. It is needed, because monitoring usually calls scripts periodically, and script should finish his work asap.


Install psacct or acct package. Then use the sa command to display CPU time used for various commands. sa man page

A nice howto from the nixCraft site.


I think it's worth looking at GNU "time" command source code. time It outputs user/system cpu time along with real elapsed time. It calls wait3/wait4 system call (if available) and otherwise it calls times system call. wait* system call returns a "rusage" struct variable and times system call returns "tms". Also, you can have a look at getrusage system call which also return very interesting timing information. time


Instead of parsing this from proc, one can use functions like getrusage() or clock_gettime() and calculate the cpu usage as a ratio or wallclock time and time the process/thread used on the cpu.

참고URL : https://stackoverflow.com/questions/1420426/how-to-calculate-the-cpu-usage-of-a-process-by-pid-in-linux-from-c

반응형