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

コードの正確性についてフィードバックを提供してください。また、子供が 1 人ではなく多数いる場合、このコードはすべての子供を組み合わせた使用法を返しますか?

4

1 に答える 1

3

セマンティクスRUSAGE_CHILDRENは、マニュアルページで非常に明確に説明されています。

RUSAGE_CHILDREN

終了して待機していた呼び出しプロセスのすべての子プロセスのリソース使用統計を返します。これらの統計には、孫によって使用されたリソースと、介在するすべての子孫が終了した子を待機している場合、さらに削除された子孫が含まれます。

子プロセスが終了し、それを待っているため、その統計がgetrusage(RUSAGE_CHILDREN, ...)呼び出しからのデータに含まれている必要があります。の前に呼び出しを置くとwaitpid、それらは含まれません。

これには、複数の子が存在する場合でも、終了して待機していれば、すべての子とさらに子孫が含まれることが明確に示されていることに注意してください。

あなたのプログラムには、あなたが見ているかもしれない奇妙な振る舞いを説明できるいくつかのバグがあります。

まず、tv_usecメンバーの型struct timevalは not time_tbutsuseconds_tです。.tv_usec型の変数に代入するtime_tと、原則としてオーバーフローする可能性があります。

次に、変数_sec_microsec変数の型time_tは ですが、%d書式指定子 to を使用して出力します。printf()これは を対象としていintます。time_tより大きいタイプの場合int(64 ビット Linux システムの場合)、これは機能しません。_microsec変数を正しい型に変更する場合も同様ですsuseconds_t

time_tここで、との型について必ずしも多くを知っているわけではありませんsuseconds_tPOSIXtime_tは、整数型または浮動小数点型のいずれかであり、suseconds_t0 から 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 システムに移植できるわけではありませんが、ほとんどの Unix システムで動作すると思います。

また、モードでファイルを開く0777ことは、テストであっても悪い習慣です。

于 2016-01-30T17:22:31.313 に答える