Team BBL
Previous Page Next Page

8.16. Process Times

In Section 1.10, we described three times that we can measure: wall clock time, user CPU time, and system CPU time. Any process can call the times function to obtain these values for itself and any terminated children.

#include <sys/times.h>

clock_t times(struct tms *buf);

Returns: elapsed wall clock time in clock ticks if OK, 1 on error


This function fills in the tms structure pointed to by buf:

   struct tms {
     clock_t  tms_utime;  /* user CPU time */
     clock_t  tms_stime;  /* system CPU time */
     clock_t  tms_cutime; /* user CPU time, terminated children */
     clock_t  tms_cstime; /* system CPU time, terminated children */
   };

Note that the structure does not contain any measurement for the wall clock time. Instead, the function returns the wall clock time as the value of the function, each time it's called. This value is measured from some arbitrary point in the past, so we can't use its absolute value; instead, we use its relative value. For example, we call times and save the return value. At some later time, we call times again and subtract the earlier return value from the new return value. The difference is the wall clock time. (It is possible, though unlikely, for a long-running process to overflow the wall clock time; see Exercise 1.6.)

The two structure fields for child processes contain values only for children that we have waited for with wait, waitid, or waitpid.

All the clock_t values returned by this function are converted to seconds using the number of clock ticks per secondthe _SC_CLK_TCK value returned by sysconf (Section 2.5.4).

Most implementations provide the geTRusage(2) function. This function returns the CPU times and 14 other values indicating resource usage. Historically, this function originated with the BSD operating system, so BSD-derived implementations generally support more of the fields than do other implementations.

Example

The program in Figure 8.30 executes each command-line argument as a shell command string, timing the command and printing the values from the tms structure.

If we run this program, we get

   $ ./a.out "sleep 5" "date"

   command: sleep 5
     real:     5.02
     user:     0.00
     sys:      0.00
     child user:     0.01
     child sys:      0.00
   normal termination, exit status = 0

   command: date
   Mon Mar 22 00:43:58 EST 2004
     real:     0.01
     user:     0.00
     sys:      0.00
     child user:     0.01
     child sys:      0.00
   normal termination, exit status = 0

In these two examples, all the CPU time appears in the child process, which is where the shell and the command execute.

Figure 8.30. Time and execute all command-line arguments
#include "apue.h"
#include <sys/times.h>

static void pr_times(clock_t, struct tms *, struct tms *);
static void do_cmd(char *);

int
main(int argc, char *argv[])
{

    int     i;

    setbuf(stdout, NULL);
    for (i = 1; i < argc; i++)
        do_cmd(argv[i]);    /* once for each command-line arg */
    exit(0);
}

static void
do_cmd(char *cmd)        /* execute and time the "cmd" */
{
     struct tms  tmsstart, tmsend;
     clock_t     start, end;
     int         status;

     printf("\ncommand: %s\n", cmd);

     if ((start = times(&tmsstart)) == -1)    /* starting values */
         err_sys("times error");

     if ((status = system(cmd)) < 0)     /* execute command */
         err_sys("system() error");

     if ((end = times(&tmsend)) == -1)       /* ending values */
         err_sys("times error");

     pr_times(end-start, &tmsstart, &tmsend);
     pr_exit(status);
}
static void
pr_times(clock_t real, struct tms *tmsstart, struct tms *tmsend)
{
    static long     clktck = 0;

    if (clktck == 0)    /* fetch clock ticks per second first time */
        if ((clktck = sysconf(_SC_CLK_TCK)) < 0)
            err_sys("sysconf error");
     printf(" real:  %7.2f\n", real / (double) clktck);
     printf(" user:  %7.2f\n",
       (tmsend->tms_utime - tmsstart->tms_utime) / (double) clktck);
     printf(" sys:   %7.2f\n",
       (tmsend->tms_stime - tmsstart->tms_stime) / (double) clktck);
     printf(" child user:   %7.2f\n",
       (tmsend->tms_cutime - tmsstart->tms_cutime) / (double) clktck);
     printf(" child sys:    %7.2f\n",
       (tmsend->tms_cstime - tmsstart->tms_cstime) / (double) clktck);
}

    Team BBL
    Previous Page Next Page