3

I'm trying to implement the times() function in C programming.

I'm using the struct tms structure which consists of the fields: tms_utime, tms_cutime, tms_stime and tms_cstime.

In order to implement the times() function in my program, I do:

  1. Before I fork and create a child, I call the times function (in the parent process).

    times(&start_tms);
    
  2. I create a pipe and I pass the times of start structure to the pipe when I'm in the child process.
  3. The child executes a simple ls -l command
  4. When the child finishes he execution, the father calls for the second time the times() function.

    times(&end_tms);
    

    Unfortunately, the times of end_tms are all zero! Weird, but I don't know why.

Some things I don't understand in my program are:

1) In the first printfs the times of the struct start are negative. Why is that? 2) When I run the program, why do I get zeros for times? What am i doing wrong?

My program is as follows:

Thanks, in advance


#include <sys/times.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int main() {

printf("test\n");

int     fd[2]; //two pointers
int nbytes;
char    string[] = "Hello, world!\n";
char    readbuffer[80];
struct tms start_tms;
struct tms end_tms;
clock_t start, end;
double cpu_time_used;

pipe(fd);

//once we have established the pipeline we fork the child
pid_t   childpid;
pid_t pid_waitpid;

//NEW MODIFICATION!!! call times before fork()!!!
times(&start_tms);

//they return negative values, but why???
printf("Test start_tms.tms_utime = %f\n\n",start_tms.tms_utime);
printf("Test start_tms.tms_cutime = %f\n\n",start_tms.tms_cutime);
printf("Test start_tms.tms_stime = %f\n\n",start_tms.tms_stime);


if((childpid = fork()) == -1)
            {
                    perror("fork");
                    exit(1);
            }

if(childpid == 0)
            {

                    /* Child process closes up input side of pipe */
                     close(fd[0]);

                   /* call times function */ 
                   /*times(&start_tms);*/


                      //REMOVED!!!!
                    //write(fd[1], string, (strlen(string)+1));
                    write(fd[1], &start_tms.tms_cutime, sizeof(clock_t));
                    write(fd[1], &start_tms.tms_utime, sizeof(clock_t));
                    write(fd[1], &start_tms.tms_stime, sizeof(clock_t));

                     //execute /bin/ls
                    execl("/bin/ls", "/bin/ls", "-r", "-t", "-l", (char *) 0);

                    exit(0);


            }
else
            {
                    /* Parent process closes up output side of pipe */
                    close(fd[1]);

                    /* NEW MODIFICATION, wait for the child!!! */
                     if( (pid_waitpid  = waitpid(childpid,NULL,0) ) == -1)
                    {
                             perror("waitpid");
                             exit(1);
                     }



                    /* call times for capturing end times */
                    times(&end_tms);

                    /* define t1, t2, variables */
                    clock_t t1,t2,t3;


                     //REMOVED!!!!
                    //nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
                    read(fd[0], &t1, sizeof(clock_t));
                    read(fd[0], &t2, sizeof(clock_t));
                    read(fd[0], &t3, sizeof(clock_t));

                    printf("Received string: %s\n\n", readbuffer);
                    printf("Test t1 = %f\n\n",t1);
                    printf("Test end_tms.tms_utime = %f\n\n",end_tms.tms_utime);
                    printf("Test end_tms.tms_cutime = %f\n\n",end_tms.tms_cutime);
                    printf("Test end_tms.tms_stime = %f\n\n",end_tms.tms_stime);

                    /* Calculate times, unfortunately return zero, but why??? */
                    double cpu_time = end_tms.tms_cutime - t1;
                    double utime = end_tms.tms_utime - t2;
                    double stime = end_tms.tms_stime - t3;

                    //Unfortunately printfs return zero, but why???
                    printf("cpu time %f\n\n",cpu_time);
                    printf("cpu Utime %f\n\n",utime);
                    printf("cpu Stime %f\n\n",stime);


}

}
Mat
  • 202,337
  • 40
  • 393
  • 406
programmer
  • 4,571
  • 13
  • 49
  • 59
  • "Implement" means you are the one writing the code for the `times()` function, which you're not doing—it's a library function that you're calling. You can say that you're "calling" or "using" it, but you are not implementing it. – Adam Rosenfield Oct 30 '11 at 16:29
  • Yeah, you are right,sorry for that...I'm using it in order to capture the times in the struct tms – programmer Oct 30 '11 at 16:42

1 Answers1

3

Your logic is very strange. The writes you do in the child simply copy data that is already available to the parent in start_tms, so your whole pipe read/write thing is unnecessary.

Secondly, clock_t is not a floating point type, it's an integral type. You can't use %f to print it. Use %jd and intmax_t to be safe in the printfs.

And you're missing #include <sys/wait.h> for waitpid. So turn on your compiler warnings, and read them.

Here's a C99 version of your code that works here:

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <inttypes.h>
#include <sys/wait.h>
#include <sys/times.h>
#include <sys/types.h>

int main() {
    struct tms start_tms;
    struct tms end_tms;

    //once we have established the pipeline we fork the child
    pid_t   childpid;

    times(&start_tms);

    printf("Test start_tms.tms_utime = %jd\n\n",  (intmax_t)start_tms.tms_utime);
    printf("Test start_tms.tms_cutime = %jd\n\n", (intmax_t)start_tms.tms_cutime);
    printf("Test start_tms.tms_stime = %jd\n\n",  (intmax_t)start_tms.tms_stime);
    printf("Test start_tms.tms_cstime = %jd\n\n",  (intmax_t)start_tms.tms_cstime);


    if((childpid = fork()) == -1)
    {
        perror("fork");
        exit(1);
    }

    if(childpid == 0)
    {
        //execute /bin/ls
        execl("/bin/ls", "/bin/ls", "-R", "-t", "-l", (char *) 0);
        exit(0);
    }
    else
    {
        /* Parent process */

        /* NEW MODIFICATION, wait for the child!!! */
        if (waitpid(childpid,NULL,0) == -1)
        {
            perror("waitpid");
            exit(1);
        }

        /* call times for capturing end times */
        times(&end_tms);

        printf("Test end_tms.tms_utime = %jd\n\n",end_tms.tms_utime);
        printf("Test end_tms.tms_cutime = %jd\n\n",end_tms.tms_cutime);
        printf("Test end_tms.tms_stime = %jd\n\n",end_tms.tms_stime);
        printf("Test end_tms.tms_cstime = %jd\n\n",end_tms.tms_cstime);

        /* Calculate times, unfortunately return zero, but why??? */
        clock_t cpu_time = end_tms.tms_cutime - start_tms.tms_cutime;
        clock_t utime = end_tms.tms_utime - start_tms.tms_utime;
        clock_t stime = end_tms.tms_stime - start_tms.tms_stime;
        clock_t cstime = end_tms.tms_cstime - start_tms.tms_cstime;

        //Unfortunately printfs return zero, but why???
        printf("cpu time %jd\n\n",  (intmax_t)cpu_time);
        printf("cpu Utime %jd\n\n", (intmax_t)utime);
        printf("cpu Stime %jd\n\n", (intmax_t)stime);
        printf("cpu CStime %jd\n\n", (intmax_t)cstime);
    }
}

If you don't have intmax_t, check the size of clock_t on your implementation and find a standard integer type that matches it, and use the appropriate format string in your printf calls.

Mat
  • 202,337
  • 40
  • 393
  • 406
  • Thank you very much for replying!When you are saying " C99 version of your code..." what is that c99 version??Also, i copied and pasted it in my system, but i still get zero.Do you get zero too??Thanks, in advance. As i can see the last "printfs" return just zero (0) not 0.0000 – programmer Oct 30 '11 at 16:36
  • C99 is the up-to-date version of C. Some compilers out there don't support parts of it, but it should be ok these days. I'm not getting 0 if the `ls` takes enough time (big directory). As I said in the answer, `clock_t` is not a floating point number, it's an integer type (whole numbers only). If you want fractions of a second, you need to divide the `clock_t` values by `CLOCKS_PER_SEC` and store that in a double (and use the `%f` format string). – Mat Oct 30 '11 at 16:45
  • (@programmer: also, stop using multiple question marks??????? One is enough. More makes you look dumb.) – Mat Oct 30 '11 at 16:46
  • Thanks, for replying. Well when i execute the program ./a.out for the "ls",it returns about 268 files and zero for all the times.Also, i typed in the command line "times /bin/ls" and the unix command returned for those 268 files the following times which are not zero (0m0.172s 0m0.028s 0m5.912s 0m0.816s). So, my program shall return non-zero values. But i can't unserstand why it doesn't return non-zero value times.Do you believe that if the dir consisted of more files, was i going to receive non-zero time values? – programmer Oct 30 '11 at 17:12
  • Replace your `exec` with `time_t t = time(NULL) + 5; while (t != time(NULL)) {};`. This will busy-loop in the child for ~5 seconds. If you still get 0 values, something is wrong. (It reports the right figures here.) – Mat Oct 30 '11 at 17:18
  • May you please send me the output of your program? – programmer Oct 30 '11 at 17:18
  • Well, i added the code you sent me and i receive for the end structure the following:[code] Test end_tms.tms_utime = 274 , Test end_tms.tms_cutime = 0 ,Test end_tms.tms_stime = 221,Test end_tms.tms_cstime = 0 )[/code]. As i can see the utime and stime are non-zero but the cstime and cutime are zero. So, the final output is:[code]cpu time 0 , cpu Utime 274,cpu Stime 221,cpu CStime 0[/code] . Do you see something wrong with the outputs? – programmer Oct 30 '11 at 17:23
  • Yeah, isn't that wrong, the fact that the the cstime and cpu time are zero? – programmer Oct 30 '11 at 17:24
  • Look, the code I posted works on my machine, and produces the expected output. I have no idea what you do to get that output, but I'm guessing you put the loop somehow in the parent process. – Mat Oct 30 '11 at 17:27
  • No, i placed the code in the child process in the "if" if(childpid == 0) { .... }. I'm running the program in a Unix shell.So, in your output, do you get non-zero results for cstime and cpu time? – programmer Oct 30 '11 at 17:30
  • Would you like to copy/paste the program here again? – programmer Oct 30 '11 at 17:31
  • Hm...i had placed the line in the clild process but i didn't erase the line for execl. Now i get non-zero values for cpu time and cpu cstime. Thanks! But i get zero values for the utime and stime. Well exec and for loop can't work together, but why? Cause i have to use the exec for my program too – programmer Oct 30 '11 at 17:35
  • Hello, i would like to ask something else.I have placed the line "time_t t = time(NULL) + 5; while (t != time(NULL)) {};" both in the child and both in the father process and don't get zero values any more.At the end, i do : long ticks = sysconf (_SC_CLK_TCK); printf("cpu time %jd\n\n", (intmax_t)cpu_time / ticks);I receive in the output then just an integer like 2 or 6.Is that right? Is that division right?Thanks, in advance – programmer Oct 30 '11 at 19:26
  • @programmer: you need to re-read your favorite C book, and focus on numeric types. Integer values are whole numbers. Floating point values are things like 1.234325. `%d` format prints whole numbers only. `%f` prints floating point numbers only. Conversion between floats and ints is lossy both ways and needs to be explicit. – Mat Oct 30 '11 at 19:34
  • Thank you.I'll check that out and re-read those.In my program i have to calculate the times, so i;m thinking of dividing them with sysconf (_SC_CLK_TCK); Is that a good idea? – programmer Oct 30 '11 at 22:40
  • Thanks, for replying. I read your first comment and i did: double count_times = (cutime + cstime) / CLOCKS_PER_SEC; printf("Test --> times = %f\n\n",count_times); . Unfortunately it outputs 0.0000, Do you have any idea, why it does that? – programmer Oct 31 '11 at 20:26
  • Well i solved it, i did: printf("User time: %f\n", (double) utime / CLOCKS_PER_SEC); Now i get a value like 0.000393 I hope it's fine, What do you think? Is that an ok value? – programmer Oct 31 '11 at 20:37