2016-01-30 7 views
1

Я пытаюсь использовать функцию getrusage в c в linux-среде и задавался вопросом, правильно ли я нахожусь на правильном пути.используя 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); 
} 

Пожалуйста, обеспечить обратную связь о правильности коды, а также, если вместо одного детей, я много, буду этот код возвращает использование для всех детей вместе взятых?

ответ

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

+0

Спасибо за объяснение, еще один вопрос. Есть ли простой способ получить время для отдельных детей, если их более одного? Я думал, чтобы в значительной степени запустить getrusage после каждого waitpid и начать вычитать, чтобы получить время для каждого chindren separatley. Также я считаю, что тип tv_usec длинный int и not suseconds_t, если только они не являются одинаковыми. – Saik

+0

@Saik: Почему да есть. Вместо 'waitpid' используйте' wait3' или 'wait4', которые заполняют' struct rusage' использование ресурсов для этого конкретного дочернего элемента и его потомков. (Если вы хотите узнать о ребенке отдельно от своих потомков отдельно, вам нужно будет дождаться, когда кто-то будет реализовывать 'wait6'). –

+0

@Saik: [POSIX говорит] (http://pubs.opengroup.org/onlinepubs/009604499/basedefs/sys/time.h.html), тип второго члена 'struct timeval' должен быть' suseconds_t'. Кажется, что она похожа на 'long int' на моей системе. –