Опубликован: 15.06.2004 | Доступ: свободный | Студентов: 2557 / 712 | Оценка: 4.35 / 3.96 | Длительность: 27:47:00
ISBN: 978-5-9556-0011-6
Лекция 12:

Время и работа с ним

На уровне языка C для опроса текущего временисекундах от начала отсчета ) служит функция time() (см. листинг 12.2).

#include <time.h>
time_t time (time_t *tloc);
Листинг 12.2. Описание функции time().

Если значение аргумента tloc отлично от пустого указателя, то текущее время не только возвращается в качестве результата, но еще и записывается по заданному адресу.

Отметим, что если тип time_t реализован как 32-разрядное целое со знаком, то в 2038-м году наступит переполнение (так называемая проблема 2038-го года ). Стандарт POSIX-2001 не справляется с проблемой в полной мере, но облегчает ее решение за счет использования более или менее абстрактного типа time_t вместо какой-либо конкретной разновидности int. Вероятно, в последующие версии стандарта POSIX будут включены требования к способности значений типа time_t представлять время в далеком будущем (например, вплоть до 10000-го года ) или явное требование не менее чем 64-разрядности.

С функцией time() ассоциирована функция difftime(), вычисляющая (в виде значения типа double ) разность в секундах между двумя моментами времени ( time1 - time0, см. листинг 12.3).

#include <time.h>
double difftime (time_t time1, time_t time0);
Листинг 12.3. Описание функции difftime().

Узнать текущее время с большей точностью позволяет функция gettimeofday() (см. листинг 12.4).

#include <sys/time.h>
int gettimeofday (struct timeval *restrict tp, 
                  void *restrict tzp);
Листинг 12.4. Описание функции gettimeofday().

Согласно стандарту POSIX-2001, описанная в заголовочном файле <sys/time.h> структура timeval содержит по крайней мере следующие поля.

time_t      tv_sec;     /* Секунды */
suseconds_t tv_usec;    /* Микросекунды */

Функция gettimeofday() записывает текущее время, выраженное в секундах и микросекундах от начала отсчета, в структуру типа timeval, на которую указывает аргумент tp. Указатель tzp должен быть пустым.

Впрочем, микросекунды - это еще на предел точности, а опрос системных часов - не предел общности. В необязательную часть стандарта POSIX-2001, регламентирующую работу с таймерами, входят функции, позволяющие опросить и установить показания заданных часов, а также узнать их разрешающую способность (см. листинг 12.5).

#include <time.h>
int clock_getres (clockid_t clock_id, 
                  struct timespec *res);
int clock_gettime (clockid_t clock_id, 
                   struct timespec *tp);
int clock_settime (clockid_t clock_id, 
                   const struct timespec *tp);
Листинг 12.5. Описание функций опроса характеристик и установки часов.

Структура timespec отличается от timeval тем, что вместо микросекунд хранит наносекунды:

time_t tv_sec;  /* Секунды */
long   tv_nsec; /* Наносекунды */

Функция clock_getres() позволяет опросить разрешающую способность часов с заданным идентификатором и поместить результат в структуру, на которую указывает аргумент res.

Функция clock_gettime() записывает в аналогичную структуру текущие показания заданных часов.

Наконец, функция clock_settime() устанавливает заданные часы на основании значений полей структуры типа timespec, на которую указывает аргумент tp.

Часы могут быть общесистемными, т. е. видимыми для всех процессов, или принадлежащими процессу (измеряют время, имеющее смысл только для конкретного процесса). Все реализации должны поддерживать общесистемные часы реального времени, измеряющие время от начала отсчета и имеющие идентификатор CLOCK_REALTIME. Интерпретация показаний других часов (если таковые имеются) стандартом не специфицируется.

Установка новых показаний для часов CLOCK_REALTIME влияет на срабатывание таймеров, взведенных на абсолютное время, но не затрагивает интервальные таймеры.

Если в системе поддерживаются монотонные часы (с идентификатором CLOCK_MONOTONIC ), они измеряют время от некоторого неспецифицированного момента в прошлом (например, от загрузки системы или начала отсчета ). Монотонные часы предназначены для измерения относительного времени. По определению, их показания нельзя установить с помощью функции clock_settime().

Применение описанных выше функций иллюстрируется программой, показанной в листинге 12.6. Возможно, при редактировании ее внешних связей придется указать дополнительные библиотеки (например, -lrt ), что является следствием использования необязательных компонентов стандарта POSIX.

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

int main (void) {
 struct timespec tmsp;
 struct timeval tmvl;
 time_t st;
 double s = 0;
 double d = 1;
 int i;

 if (clock_getres (CLOCK_REALTIME, &tmsp) == -1) {
    perror ("CLOCK_GETRES");
    return (1);
 }
 printf ("Разрешающая способность общесистемных часов: %ld нсек.\n",
            tmsp.tv_nsec);

 if (clock_gettime (CLOCK_REALTIME, &tmsp) == -1) {
    perror ("CLOCK_GETTIME");
    return (2);
 }
 printf ("Текущее время по общесистемным часам: %ld сек. %ld нсек.\n",
            tmsp.tv_sec, tmsp.tv_nsec);

(void) gettimeofday (&tmvl, NULL);
 printf ("Текущее время, функция gettimeofday(): %ld сек. %ld мксек.\n",
            tmvl.tv_sec, tmvl.tv_usec);

 (void) time (&st);
 for (i = 1; i <= 100000000; i++) {
    s += d / i;
    d = -d;
 }
 printf ("Время выполнения цикла: %g сек.\n", difftime (time (NULL), st));

 return (0);
}
Листинг 12.6. Пример программы, использующей функции опроса показаний часов реального времени.

Результаты работы этой программы могут выглядеть так, как показано в листинге 12.7.

Разрешающая способность общесистемных часов: 
10000000 нсек.
Текущее время по общесистемным часам: 
1072534678 сек. 296598000 нсек.
Текущее время, функция gettimeofday(): 
1072534678 сек. 296637 мксек.
Время выполнения цикла: 15 сек.
Листинг 12.7. Возможные результаты работы программы, использующей функции опроса показаний часов реального времени.
Антон Коновалов
Антон Коновалов

В настоящее время актуальный стандарт - это POSIX 2008 и его дополнение POSIX 1003.13
Планируется ли актуализация материалов данного очень полезного курса?