我想以编程方式[在C中]为Linux中给定的进程ID计算CPU使用率%。
如何获得给定进程的实时CPU使用率百分比?
为了进一步说明:
- 我应该能够确定所提供的processid或进程的CPU使用率。
- 该进程不必是子进程。
- 我想要“ C”语言的解决方案。
我想以编程方式[在C中]为Linux中给定的进程ID计算CPU使用率%。
如何获得给定进程的实时CPU使用率百分比?
为了进一步说明:
Answers:
您需要从中解析出数据/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时间。您需要对这条线上的值求和才能得到time_total
度量。
同时读取utime
并stime
进行过程中,你有兴趣,并阅读time_total
来自/proc/stat
。然后睡一秒钟左右,然后再次阅读它们。现在,您可以使用以下命令计算采样时间内该进程的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
了多少次调试,并告诉您一个CPU已执行了多少次调试。单进程。
man proc
是您的朋友(搜索/proc/[pid]/stat
)
/proc
伪文件系统:标准C文件系统访问功能(如fopen()
和scanf()
)的讲授并不重要。
getrusage()可以帮助您确定当前进程或其子进程的使用情况
更新: 我不记得一个API。但是所有详细信息都将在/ proc / PID / stat中,因此,如果我们可以解析它,则可以得到百分比。
编辑: 由于CPU%不能直接计算,因此您可以在此处使用采样类型的东西。在某个时间点读取PID的ctime和utime,并在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);
我写了两个基于cafs答案的小C函数来计算进程的用户+内核cpu使用量:https : //github.com/fho/code_snippets/blob/master/c/getusage.c
您可以阅读proc的联机帮助页获取更多详细信息,但总而言之,您可以阅读/ proc / [number] / stat以获取有关进程的信息。“ ps”命令也使用此命令。
所有字段及其scanf格式说明符均记录在proc manpag中。
以下是复制的联机帮助页中的一些信息(很长):
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
当您想要监视指定的进程时,通常是通过脚本来完成的。这是perl的示例。这样将百分比与top相同,将其缩放到一个CPU。然后,当某个进程正在使用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;
}
希望它能对您进行任何监视。当然,您应该使用scanf或其他C函数将我曾经使用的所有perl正则表达式转换为C源代码。当然,睡眠不是强制性的1秒。您可以随时使用。效果是,您将在指定的时间段内获得平均负载。当您将其用于监视时,您当然应该将最后的值放在外面。这是必需的,因为监视通常会定期调用脚本,并且脚本应尽快完成其工作。
使用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
.
.
.