10

I want to read the CPU utilization stats from a C program, I am interested in the percentage of use of CPU, steal time etc. These stats are shown in the 3rd row from the top command.

I tried to parse top 's output with awk (top -n 1 -b | awk '{print $0}'), but it seems that top gives always the same 'fictional' values before it starts showing correct stats.

Is there a way from code, or by parsing some command's output to get the CPU utilization stats?

Edit:

The platform is Linux

Thank you.

1
  • Sure, but there is no standard way. Precise the target OS(es).
    – jlliagre
    Commented Sep 27, 2011 at 20:44

4 Answers 4

7

You want to read the first few lines of /proc/stat. You'll need to read it twice, a measured time apart, and subtract the first set of numbers from the second. The lines look like this:

cpu  1526724 408013 600675 541100340 2861417 528 14531 0 0 0
cpu0 344507 77818 251244 134816146 1119991 324 13283 0 0 0
cpu1 502614 324065 179301 133991407 1631824 136 906 0 0 0
cpu2 299080 3527 79456 136144067 103208 59 255 0 0 0
cpu3 380521 2602 90672 136148719 6393 7 86 0 0 0
intr 2111239193 344878476 16943 ...

The first line is aggregate for all cores. The next lines show each core. When you see the line that start with intr, you know to stop parsing.

Each number is the amount of time the CPU has spent in a particular state. The units are typically hundredths of a second. The fields are user, nice, system, idle, iowait, irq, softirq, steal, guest, and guest_nice.

The authoritative documentation is, of course, the source code. If you have a copy of the Linux kernel source handy, look at fs/proc/stat.c, particularly the show_stat function.

2
  • Do you know at what frequency the proc/stat is being updated? like once every 1ms or something, thank you.
    – 0xFF
    Commented Sep 29, 2011 at 20:19
  • 1
    They're not real files. Their contents are calculated when you open them. Commented Sep 30, 2011 at 0:13
3

There is some example on the web that shows how to read /proc/pid/stat in C.

You could read utime or stime values at two distinct moments and compute the desired cpu utilization stats. (I guess top uses this raw data too.)

(I forgot: this is linux specific.)

0

I have done this using sysinfo below is snippet

#include "sysinfo.h"

getstat(cpu_use,cpu_nic, cpu_sys, cpu_idl, cpu_iow, cpu_xxx, cpu_yyy, cpu_zzz, pgpgin, pgpgout, pswpin, pswpout, intr, ctxt, &running,&blocked, &dummy_1, &dummy_2);

float cpuconsumption = (float) ((   (float) ((*cpu_use) + (*cpu_sys)) / (float)((*cpu_use)+(*cpu_sys)+(*cpu_idl)))*100);
0

In case anybody wanted some quick cpu usage values directly from top inside a c application, this snippet just opens a pipe, and returns the last line of the top process with the cpu information.

/**
 * Get last cpu load as a string (not threadsafe)
 */
static char* getCpuLoadString()
{
    /*
     * Easiest seems to be just to read out a line from top, rather than trying to calc it ourselves through /proc stuff
     */
    static bool started = false;
    static char buffer[1024];
    static char lastfullline[256];
    static int bufdx;
    static FILE *fp;

    if(!started) {
        /* Start the top command */

        /* Open the command for reading. */
        fp = popen("top -b  -d1", "r");
        if (fp == NULL) {
          printf("Failed to run top command for profiling\n" );
          exit(1);
        }

        /* Make nonblocking */
        int flags;
        flags = fcntl(fileno(fp), F_GETFL, 0);
        flags |= O_NONBLOCK;
        fcntl(fileno(fp), F_SETFL, flags);

        started = true;
    }


    /*
     * Read out the latest info, and remember the last full line
     */
    while( fgets (buffer + bufdx, sizeof(buffer) - bufdx, fp)!=NULL ) {
        /* New data came in. Iteratively shift everything until a newline into the last full line */
        char *newlinep;
        while((newlinep = strstr(buffer, "\n"))) {
            int shiftsize = (newlinep - buffer + 1);
            *newlinep = 0; /* Nullterminate it for strcpy and strstr */
            /* Check if the line contained "cpu" */
            if(strstr(buffer, "Cpu")) {
                strncpy(lastfullline, buffer, sizeof(lastfullline) - 1); /* Copy full line if it contained cpu info */
            }
            memmove(buffer, buffer + shiftsize, shiftsize); /* Shift left (and discard) the line we just consumed */
        }
    }

    /*
     * Return the last line we processed as valid output
     */
    return lastfullline;
}

I then simply call printf(" %s\n", getCpuLoadString()); every second

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .