2

我正在尝试如何在 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);
}

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

4

1 回答 1

3

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

RUSAGE_CHILDREN

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

由于您的子进程已经终止并且您已经等待它,因此它的统计信息应该包含在您getrusage(RUSAGE_CHILDREN, ...)调用的数据中。如果您将调用放在 之前waitpid,它们将不包括在内。

请注意,它清楚地表明这包括所有孩子,即使有多个孩子,以及进一步的后代,只要他们已经终止并被等待。

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

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

接下来,您的_sec_microsec变量的类型为,但您使用格式说明符 totime_t打印它们,这适用于. 如果类型大于(在 64 位 Linux 系统上就是这种情况),那么这将不起作用。当您将变量更改为正确的类型时也是如此。%dprintf()inttime_tint_microsecsuseconds_t

现在我们不一定对time_tand的类型了解很多suseconds_tPOSIX只说它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是一种不好的做法,即使对于测试也是如此。

于 2016-01-30T17:22:31.313 回答