Как правильно использовать clock_gettime ()? - PullRequest
0 голосов
/ 10 декабря 2018

Я пробовал эту функцию в программе на Си, и она продолжает печатать в неправильное время.Это мой код на данный момент:

#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <sys/resource.h>

int main( int argc, char **argv ){
    struct timespec start, finish;
    clock_gettime( CLOCK_REALTIME, &start );
    sleep( 1 );
    clock_gettime( CLOCK_REALTIME, &finish );
    printf( "%f\n", ((double) (finish.tv_nsec - start.tv_nsec))/((double) 100000) );
    return 0;
}

Я не уверен, является ли это аномалией, вызванной ошибками округления при преобразовании в double, или я неправильно использую функцию clock_gettime(), но я ожидал, что он выдаст 1 секунду, и вместо этого он выдаст 1,27 секунды.

1 Ответ

0 голосов
/ 10 декабря 2018

Необходимо учитывать tv_sec член структуры при расчете разницы во времени между двумя значениями, возвращаемыми clock_gettime().

tv_nsec - это числонаносекунд в течение текущей секунды.Он колеблется (в теории) от 0 до 999 999 999.Это позволяет хранить целое число целых секунд в tv_sec и долю секунды в tv_nsec.Фактическое решение - другая проблема: см. clock_getres().Например, на Mac разрешение составляет микросекунды, хотя они выражаются в наносекундах.

Рассмотрите возможность использования кода, подобного следующему:

#include <stdio.h>
#include <time.h>
#include <unistd.h>

enum { NS_PER_SECOND = 1000000000 };

void sub_timespec(struct timespec t1, struct timespec t2, struct timespec *td)
{
    td->tv_nsec = t2.tv_nsec - t1.tv_nsec;
    td->tv_sec  = t2.tv_sec - t1.tv_sec;
    if (td->tv_sec > 0 && td->tv_nsec < 0)
    {
        td->tv_nsec += NS_PER_SECOND;
        td->tv_sec--;
    }
    else if (td->tv_sec < 0 && td->tv_nsec > 0)
    {
        td->tv_nsec -= NS_PER_SECOND;
        td->tv_sec++;
    }
}

int main(void)
{
    struct timespec start, finish, delta;
    clock_gettime(CLOCK_REALTIME, &start);
    sleep(1);
    clock_gettime(CLOCK_REALTIME, &finish);
    sub_timespec(start, finish, &delta);
    printf("%d.%.9ld\n", (int)delta.tv_sec, delta.tv_nsec);
    return 0;
}

При запуске (как cgt61) я получаю такие результаты:

$ cgt61
1.004930000
$ cgt61
1.004625000
$ cgt61
1.003023000
$ cgt61
1.003343000
$

Это было проверено на Mac;Вы можете видеть, что последние три цифры всегда нули.В виртуальной машине Linux (Ubuntu 18.04 на Mac) мне пришлось добавить #define _POSIX_C_SOURCE 200809L в код (потому что я компилирую с -std=c11; если бы я использовал -std=gnu11, у меня все было бы в порядке), и вывод был:

$ ./cgt61
1.000589528
$
...