Используя 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
это плохая практика, даже для тестирования.