How to calculate the CPU usage of a process by PID in Linux from C?

CLinuxCpu Usage

C Problem Overview


I want to programmatically [in C] calculate CPU usage % for a given process ID in Linux.

How can we get the realtime CPU usage % for a given process?

To make it further clear:

  • I should be able to determine the CPU usage for the provided processid or process.
  • The process need not be the child process.
  • I want the solution in 'C' language.

C Solutions


Solution 1 - C

You need to parse out the data from /proc/<PID>/stat. These are the first few fields (from Documentation/filesystems/proc.txt in your kernel source):

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

You're probably after utime and/or stime. You'll also need to read the cpu line from /proc/stat, which looks like:

cpu  192369 7119 480152 122044337 14142 9937 26747 0 0

This tells you the cumulative CPU time that's been used in various categories, in units of jiffies. You need to take the sum of the values on this line to get a time_total measure.

Read both utime and stime for the process you're interested in, and read time_total from /proc/stat. Then sleep for a second or so, and read them all again. You can now calculate the CPU usage of the process over the sampling time, with:

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);

Make sense?

Solution 2 - C

getrusage() can help you in determining the usage of current process or its child

Update: I can't remember an API. But all details will be in /proc/PID/stat, so if we could parse it, we can get the percentage.

EDIT: Since CPU % is not straight forward to calculate, You could use sampling kind of stuff here. Read ctime and utime for a PID at a point in time and read the same values again after 1 sec. Find the difference and divide by hundred. You will get utilization for that process for past one second.

(might get more complex if there are many processors)

Solution 3 - C

Easy step to step for beginners like me:

  1. Read the first line of /proc/stat to get total_cpu_usage1.
    sscanf(line,"%*s %llu %llu %llu %llu",&user,&nice,&system,&idle);
    total_cpu_usage1 = user + nice + system + idle;
  1. Read /proc/pid/stat where pid is the PID of the process you want to know the CPU usage, like this:
    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. Now sum usertime and systemtime and get proc_times1
  2. Now wait 1 second or more
  3. Do it again, and get total_cpu_usage2 and proc_times2

The formula is:

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

You can get the amount of CPU's from /proc/cpuinfo.

Solution 4 - C

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

Solution 5 - 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.

Solution 6 - C

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

Solution 7 - C

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

Solution 8 - C

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.

Solution 9 - C

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.

Solution 10 - C

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

Solution 11 - C

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.

Solution 12 - C

Use strace found the CPU usage need to be calculated by a time period:

# 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
.
.
.

Solution 13 - C

htop -p <pid-of-process> . It will list all the cpus and their utilisation.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioncodingfreakView Question on Stackoverflow
Solution 1 - CcafView Answer on Stackoverflow
Solution 2 - Cvpram86View Answer on Stackoverflow
Solution 3 - CzizzuView Answer on Stackoverflow
Solution 4 - CfhoView Answer on Stackoverflow
Solution 5 - CAndre MillerView Answer on Stackoverflow
Solution 6 - CJames AndersonView Answer on Stackoverflow
Solution 7 - CMohan RamView Answer on Stackoverflow
Solution 8 - CZnikView Answer on Stackoverflow
Solution 9 - CLifeguardView Answer on Stackoverflow
Solution 10 - Cuser3288728View Answer on Stackoverflow
Solution 11 - CensonicView Answer on Stackoverflow
Solution 12 - CJinming LvView Answer on Stackoverflow
Solution 13 - Ckushagra deepView Answer on Stackoverflow