Linux에서 주어진 프로세스 ID에 대해 프로그래밍 방식으로 [C에서] CPU 사용량 %를 계산하고 싶습니다.
주어진 프로세스에 대한 실시간 CPU 사용량 %를 어떻게 얻을 수 있습니까?
더 명확하게하려면 :
- 제공된 프로세스 ID 또는 프로세스에 대한 CPU 사용량을 확인할 수 있어야합니다.
- 프로세스가 하위 프로세스 일 필요는 없습니다.
- 'C'언어로 된 솔루션을 원합니다.
Linux에서 주어진 프로세스 ID에 대해 프로그래밍 방식으로 [C에서] CPU 사용량 %를 계산하고 싶습니다.
주어진 프로세스에 대한 실시간 CPU 사용량 %를 어떻게 얻을 수 있습니까?
더 명확하게하려면 :
답변:
에서 데이터를 구문 분석해야합니다 /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
측정 값 을 얻으려면이 선에있는 값의 합계를 얻어야합니다 .
관심있는 프로세스 utime
와 stime
에서 모두 읽고 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);
말이 되나?
/proc/stat
CPU가 총 /proc/<PID>/stat
실행 한 jiff의 수를 알려주고 a에 의해 실행 된 jiff의 수를 알려주는 것입니다. 단일 프로세스.
man proc
당신의 친구 (검색입니다 /proc/[pid]/stat
)
/proc
가상 파일 시스템 : 같은 표준 C 파일 시스템 액세스 기능의 가르침을 fopen()
및 scanf()
지점 옆에있다.
getrusage () 는 현재 프로세스 또는 하위 프로세스의 사용을 결정하는 데 도움이 될 수 있습니다.
업데이트 : API가 기억 나지 않습니다. 그러나 모든 세부 사항은 / proc / PID / stat에 있으므로 파싱 할 수 있다면 백분율을 얻을 수 있습니다.
편집 : CPU %는 계산하기가 쉽지 않기 때문에 여기에서 샘플링 종류를 사용할 수 있습니다. 특정 시점에서 PID에 대한 ctime 및 utime을 읽고 1 초 후에 동일한 값을 다시 읽습니다. 차이를 찾아서 백으로 나눕니다. 지난 1 초 동안 해당 프로세스에 대한 활용도를 얻을 수 있습니다.
(프로세서가 많으면 더 복잡해질 수 있음)
나 같은 초보자를위한 쉬운 단계 :
/proc/stat
를 얻으려면 의 첫 번째 줄을 읽으십시오 total_cpu_usage1
. sscanf(line,"%*s %llu %llu %llu %llu",&user,&nice,&system,&idle);
total_cpu_usage1 = user + nice + system + idle;
/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
....)
usertime
및 systemtime
및 GETproc_times1
total_cpu_usage2
,proc_times2
공식은 다음과 같습니다.
(number of processors) * (proc_times2 - proc_times1) * 100 / (float) (total_cpu_usage2 - total_cpu_usage1)
에서 CPU의 양을 얻을 수 있습니다 /proc/cpuinfo
.
#include <unistd.h>
,이 메서드를 호출int nb = sysconf(_SC_NPROCESSORS_ONLN);
프로세스의 user + kernel cpu 사용량을 계산하기 위해 cafs 답변을 기반으로 두 개의 작은 C 함수를 작성했습니다. https://github.com/fho/code_snippets/blob/master/c/getusage.c
자세한 내용 은 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.
ps aux
더 낫다 :)
"pidstat"명령을 살펴보면 정확히 필요한 것처럼 들립니다.
이것은 내 해결책입니다 ...
/*
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
특정 프로세스를 모니터링하려는 경우 일반적으로 스크립팅으로 수행됩니다. 다음은 펄의 예입니다. 이것은 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 초는 필수는 아닙니다. 언제든지 사용할 수 있습니다. 효과는 지정된 기간에 평균 부하를 받게됩니다. 모니터링에 사용할 때 물론 마지막 값은 외부에 넣어야합니다. 모니터링은 보통 주기적으로 스크립트를 호출하고 스크립트는 최대한 빨리 작업을 완료해야하기 때문에 필요합니다.
설치 psacct
또는 acct
패키지. 그런 다음 sa
명령을 사용하여 다양한 명령에 사용 된 CPU 시간을 표시합니다. sa man 페이지
nixCraft 사이트 의 멋진 하우투 .
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
.
.
.