使用getrusage为父母和孩子们腾出时间

时间:2016-01-30 10:44:22

标签: c linux getrusage

我正在尝试如何在Linux环境中使用c中的getrusage函数,并且想知道我是否在正确的轨道上。

我写了一个小程序,以确保我在申请项目之前了解getrusage的工作原理。我想分别为父进程和子进程获取用户/内核时间。

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);
}

请提供一些关于代码正确性的反馈,如果不是一个孩子,我有很多,这段代码会返回所有孩子的用法吗?

1 个答案:

答案 0 :(得分:2)

语义RUSAGE_CHILDREN在手册页中非常清楚地解释了:

  

RUSAGE_CHILDREN

     

返回已终止的调用进程的所有子级的资源使用情况统计信息                 并等待。这些统计数据将包括孙子孙女使用的资源                 如果所有介入的后代等待他们的终止,则进一步移除后代                 孩子。

由于您的子流程已终止且您已等待,因此其统计信息应包含在getrusage(RUSAGE_CHILDREN, ...)电话的数据中。如果您在waitpid之前拨打电话,则不会将其包括在内。

请注意,它清楚地表明这包括所有孩子,即使有多个孩子,还有其他后代,只要他们已经终止并等待。

我确实看到你程序中的一些错误可以解释你可能会看到的任何奇怪的行为。

首先,tv_usec struct timeval成员的类型不是time_t,而是suseconds_t。原则上,将.tv_usec分配给time_t类型的变量可能会溢出它。

接下来,您的_sec_microsec变量的类型为time_t,但是您使用%d格式说明符将其打印到printf(),这是预期的为int。如果time_t的类型大于int(在64位Linux系统上就是这种情况),那么这将无效。将_microsec变量更改为正确类型suseconds_t时也是如此。

现在,我们不一定非常了解time_tsuseconds_t的类型。 POSIX仅表示time_t可以是整数或浮点类型,suseconds_t是一个有符号整数类型,可以表示0到1000000之间的数字。

在所有Linux平台上,据我所知,time_t是一个有符号整数类型,所以我相信我们可以安全地做到

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

这不一定能够移植到所有Unix系统,但我认为它适用于大多数系统。

此外,打开模式0777的文件是一种不好的做法,即使是测试也是如此。