Используя getrusage, чтобы получить время для родителей и детей

Я пытаюсь, как использовать функцию getrusage в c в среде Linux, и мне было интересно, если я на правильном пути.

Я написал небольшую программу, чтобы убедиться, что я понимаю, как работает 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 ответ

Семантика 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_t а также suseconds_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 это плохая практика, даже для тестирования.

Другие вопросы по тегам