如何从C中计算Linux中PID进程的CPU使用率?
我想以编程方式(在C中)计算Linux中给定进程ID的CPU使用率%。
我们如何获得给定进程的实时CPU使用率?
为了进一步明确:
- 我应该能够确定提供的processid或进程的CPU使用率。
- 这个过程不一定是孩子的过程。
- 我想用“C”语言来解决这个问题。
您需要parsing/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
。 你还需要读取/proc/stat
的cpu
行,如下所示:
cpu 192369 7119 480152 122044337 14142 9937 26747 0 0
这告诉你在各种类别中使用的累积CPU时间,以jiffies为单位。 你需要把这一行的值总和得到一个time_total
度量。
阅读你感兴趣的过程,然后阅读/proc/stat
time_total
。 然后睡一会儿,再读一遍。 现在可以计算采样时间内进程的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()可以帮助您确定当前进程或其subprocess的使用情况
更新:我不记得一个API。 但所有的细节将在/ proc / PID / stat中,所以如果我们可以parsing它,我们可以得到的百分比。
编辑:由于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是你想知道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获取cpus的数量
我写了两个基于cafs的小C函数来计算一个进程的user + kernel cpu使用情况: https : //github.com/fho/code_snippets/blob/master/c/getusage.c
您可以阅读proc的manpage以获得更多详细信息,但总而言之,您可以阅读/ proc / [number] / stat以获取有关进程的信息。 这也被'ps'命令使用。
所有的字段和他们的scanf格式说明符logging在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.
这是我的解决scheme…
/* 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
看看“pidstat”命令,听起来就像你所需要的。
当你想监视指定的进程,通常是通过脚本来完成的。 这里是perl的例子。 这样把百分数和上面的一样,把它缩小到一个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函数来转换我曾经使用过的C源代码的perl正则expression式。 当然,1秒睡觉是不是强制性的。 你可以随时使用。 效果是,你会在规定的时间内获得平均的负载。 当你将它用于监视,当然最后值应该放在外面。 这是必要的,因为监视通常会定期调用脚本,脚本应尽快完成工作。
那么捕捉(grep-ing)top的输出呢。
安装psacct
或acct
软件包。 然后使用sa
命令显示用于各种命令的CPU时间。 一个男人的页面
从nixCraft网站的一个不错的howto 。
我认为这是值得一看的GNU“时间”命令源代码。 时间它将输出用户/系统CPU时间以及实际的时间。 它调用wait3 / wait4系统调用(如果可用),否则调用系统调用次数。 等待系统调用返回一个“rusage”结构variables,系统调用返回“tms”。 此外,你可以看看getrusage系统调用,这也返回非常有趣的时间信息。 时间
可以使用像getrusage()或clock_gettime()这样的函数来计算cpu的使用情况,而不是使用proc来parsing这个函数。