简体   繁体   中英

using getrusage to get the time for parent and children

I am trying how to use getrusage function in c in linux environment and was wondering if I am on a right track.

I wrote a small program to make sure I understand how getrusage works before applying to my project. I want to get the user/kernel times for both parent and child processes separately.

void stupidFunction();
void childSort();


int main(void)
{

  pid_t parent_pid=getpid();

  struct rusage parent_before_function_usage;
  getrusage(RUSAGE_SELF,&parent_before_function_usage);

  time_t  parent_before_function_user_usage_sec=parent_before_function_usage.ru_utime.tv_sec;
  time_t  parent_before_function_user_usage_microsec=parent_before_function_usage.ru_utime.tv_usec;
  time_t  parent_before_function_cpu_usage_sec =parent_before_function_usage.ru_stime.tv_sec;
  time_t  parent_before_function_cpu_usage_microsecsec =parent_before_function_usage.ru_stime.tv_usec;

  stupidFunction();

  pid_t pid;



  if((pid = fork()) <0)
  {
    fprintf(stderr,"Failed to create a fork process\n");
  }
  else if (pid == 0)
  {
    childSort();
  }



  int status;



  waitpid(-1,&status,0);


  printf("in parent\n");

  struct rusage parent_after_function_usage;
  getrusage(RUSAGE_SELF,&parent_after_function_usage);

  time_t parent_after_function_user_usage_sec=parent_after_function_usage.ru_utime.tv_sec;
  time_t parent_after_function_user_usage_microsec=parent_after_function_usage.ru_utime.tv_usec;
  time_t parent_after_function_cpu_usage_sec =parent_after_function_usage.ru_stime.tv_sec;
  time_t parent_after_function_cpu_usage_microsecsec =parent_after_function_usage.ru_stime.tv_usec;

  time_t parent_real_user_usage_sec=parent_after_function_user_usage_sec - parent_before_function_user_usage_sec;
  time_t parent_real_user_usage_microsec= parent_after_function_user_usage_microsec - parent_before_function_user_usage_microsec;
  time_t parent_real_cpu_usage_sec=parent_after_function_cpu_usage_sec - parent_before_function_cpu_usage_sec;
  time_t parent_real_cpu_usage_microsec = parent_after_function_cpu_usage_microsecsec - parent_before_function_cpu_usage_microsecsec;

  printf("User mode CPU time for parent: %d seconds, %d microseconds\n",parent_real_user_usage_sec,parent_real_user_usage_microsec);
  printf("Kern mode CPU time for parent: %d seconds, %d microseconds\n",parent_real_cpu_usage_sec,parent_real_cpu_usage_microsec);


  struct rusage child_function_usage;
  getrusage(RUSAGE_CHILDREN,&child_function_usage);



  time_t all_children_user_usage_sec=child_function_usage.ru_utime.tv_sec;
  time_t all_children_user_usage_microsec=child_function_usage.ru_utime.tv_usec;
  time_t all_children_cpu_usage_sec =child_function_usage.ru_stime.tv_sec;
  time_t all_children_cpu_usage_microsec =child_function_usage.ru_stime.tv_usec;

  printf("User mode CPU time for all children: %d seconds, %d microseconds\n",all_children_user_usage_sec,all_children_user_usage_microsec);
  printf("Kern mode CPU time for all children: %d seconds, %d microseconds\n",all_children_cpu_usage_sec,all_children_cpu_usage_microsec);


  return 0;
}



void stupidFunction()
{

  int i=0;

  while(i<900000000)
  {
    //  printf("%d\n",i);
    i+=1;
  }

}


void childSort()
{
  printf("in childSort\n");

  int fd[2];
  fd[0]=open("file1", O_RDONLY,0777);
  fd[1]=open("file2", O_WRONLY,0777);

  dup2(fd[0],0);
  dup2(fd[1],1);

  char* execArgs[2];
  execArgs[0]="sort";
  execArgs[1]=NULL;

  execvp(execArgs[0],execArgs);
}

Please provide some feedback about the correctness of the code and also, if instead of one children, I have many, will this code return the usage for all children combined ?

The semantics RUSAGE_CHILDREN are pretty clearly explained in the man page:

RUSAGE_CHILDREN

Return resource usage statistics for all children of the calling process that have terminated and been waited for. These statistics will include the resources used by grandchildren, and further removed descendants, if all of the intervening descendants waited on their terminated children.

Since your child process has terminated and you have waited for it, its statistics should be included in the data from your getrusage(RUSAGE_CHILDREN, ...) call. If you put the call before the waitpid , they wouldn't be included.

Note it says clearly that this includes all children, even if there is more than one, and further descendants, provided they have terminated and been waited for.

I do see some bugs in your program that could explain any odd behavior you might be seeing.

First, the type of the tv_usec member of struct timeval is not time_t but suseconds_t . Assigning .tv_usec to a variable of type time_t might overflow it, in principle.

Next, your _sec and _microsec variables are of type time_t , but you print them with the %d format specifier to printf() , which is intended for int . If time_t is of a type larger than int (which is the case on 64-bit Linux systems) then this will not work. The same goes when you change your _microsec variables to be of the correct type suseconds_t .

Now we don't necessarily know much about the types of time_t and suseconds_t . POSIX says only that time_t can be either an integer or floating-point type, and that suseconds_t is a signed integer type that can represent numbers from 0 to 1000000.

On all Linux platforms, as far as I know, time_t is a signed integer type, so I believe we could safely do

 time_t sec = ... ;
 time_t microsec = ...;
 printf("Time is %jd seconds and %jd microseconds\n", (intmax_t)sec, (intmax_t)microsec);

This won't necessarily be portable to all Unix systems, but I think it will work on most of them.

Also, opening files with mode 0777 is a bad practice, even for testing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM