anthozep
anthozep

Reputation: 333

C Program to get CPU usage for a PID and all its children

I have a C program that parses the /proc//stat directory to calculate the average CPU utilization over a period of 5 seconds:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#define ITERATIONS 5

int main(int argc, char *argv[])
{
    if (argc != 2) {
        printf( "usage: %s <PID>\n", argv[0] );
        return(-1);
    }

    long double a[4], b[4];
    long double pidTime = 0.0;
    long int clk;
    int i;
    FILE *fp;
    char stat[1024];

    clk = sysconf(_SC_CLK_TCK);

    if (clk == -1) {
        printf("Could not determine clock ticks per second");
        return(-1);
    }

    char *pidPath = malloc(strlen("/proc/stat/")+strlen(argv[1])+1);
    if (pidPath == NULL) {
        printf("Could not allocate memory for str\n");
        return(-1);
    } else {
        strcpy(pidPath, "/proc/");
        strcat(pidPath, argv[1]);
        strcat(pidPath, "/stat");
    }

    for(i = 0; i < ITERATIONS; i++)
    {
        fp = fopen(pidPath,"r");
        if (fp == NULL) {
            perror(pidPath);
            return(-1);
        } else {
            fgets(stat, sizeof(stat), fp);
            sscanf(stat,"%*d %*s %*c %*d %*d %*d %*d %*d %*u %*lu %*lu %*lu %*lu %Lf %Lf %Lf %Lf %*ld %*ld %*ld %*ld %*llu",&a[0],&a[1],&a[2],&a[3]);
            fclose(fp);
            sleep(1);
        }

        fp = fopen(pidPath,"r");
        if (fp == NULL) {
            perror(pidPath);
            return(-1);
        } else {
            fgets(stat, sizeof(stat), fp);
           sscanf(stat,"%*d %*s %*c %*d %*d %*d %*d %*d %*u %*lu %*lu %*lu %*lu %Lf %Lf %Lf %Lf %*ld %*ld %*ld %*ld %*llu",&b[0],&b[1],&b[2],&b[3]);
            fclose(fp);
        }

        pidTime += (((b[0]+b[1]+b[2]+b[3]) - (a[0]+a[1]+a[2]+a[3])));
    }

    pidTime = (pidTime / (clk * ITERATIONS));
    printf("pidCPU=%Lf\n", pidTime);
    printf("%ld", clk);
    free(pidPath);
    return(0);
}

From what I understand the relevant fields in stat are:

For a single process, this works great, but when I have a process that forks, or is multithreaded, this breaks down. Do the cutime and cstime counters only work when the parent is waiting for the child processes? How can I calculate the total usage of the process tree rooted at PID?

Upvotes: 1

Views: 2880

Answers (1)

Jerzy
Jerzy

Reputation: 760

Yes, the parent needs to wait for the CPU time of the children to be added in (see manual entry for getrusage link). Also see this answer for more details.

Upvotes: 1

Related Questions