Выбрать главу

Функция strptime() возвращает указатель на символ в s — символ, находящийся за последним прочитанным во время разбора.

Функция strptime(), к сожалению, не определена ни в ANSI/ISO, ни в POSIX, что ограничивает ее переносимость.

18.1.3. Ограничения, связанные со временем

В 32-разрядных системах Linux, как и в большинстве систем Unix, переменная time_t является целым числом со знаком длиной 32 бита. Это означает, что в 10:14:07 вечера 18 января (четверг) 2038 года она переполнится. Поэтому время 10:14:08 вечера 18 января (четверг) 2038 года будет представлено как 3:45:52 вечера 13 декабря (пятница) 1901 года. Как видите, система Linux не проявляет "проблему 2000-го года" (поскольку используются собственные библиотеки времени), однако с ней связана "проблема 2038-го года".

На 64-разрядных платформах переменная time_t является соответственно 64-битовым числом со знаком. Это действительно эффективное решение, поскольку 64-битовое время со знаком можно назвать астрономическим.

Для того чтобы определить начальное время, текущее время, конечное время для используемой системы можно создать и запустить данную программу daytime.с.

 1: /* daytime.с */

 2:

 3: #include <stdio.h>

 4: #include <sys/time.h>

 5: #include <unistd.h>

 6:

 7: int main () {

 8:  struct timeval tv;

 9:  struct timezone tz;

10:  time_t now;

11:  /* beginning_of_time — это наименьшее значении, измеряемое time_t*/

12:  time_t beginning_of_time = 1L<<(sizeof(time_t)*8 - 1);

13:  /* end_of_time - это наибольшее значение, измеряемое time_t */

14:  time_t end_of_time = ~beginning_of_time;

15:

16:  printf("time_t имеет %d бит в длину\n\n", sizeof(time_t) *8);

17:

18:  gettimeofday(&tv, &tz);

19:  now = tv.tv_sec;

20:  printf("Текущее время дня, представленное в виде структуры timevaclass="underline" \n"

21:   "tv.tv_sec = 0x%08x, tv.tv_usec = 0x%08х\n"

22:   "tz.tz_minuteswest = 0x%08х, tz.tz_dsttime = 0x%08x\n\n",

23:   tv.tv_sec, tv.tv_usec, tz.tz_minuteswest, tz.tz_dsttime);

24:

25:  printf("Демонстрация ctime()%s:\n",

26:   sizeof(time_t)*8 <= 32 ? "" :

27:   " (может зависнуть после печати первой строки; нажмите "

28:   "Control-C)") ;

29:  printf("текущее время: %s", ctime(&now));

30:  printf("начало времени: %s", ctime(&beginning_of_time));

31:  printf("конец времени: %s", ctime(&end_of_time));

32:

33:  exit(0);

34: }

К сожалению, функция ctime() является итеративной по своей природе. Это означает, что она (при любых практических целях) никогда не прерывает свою работу в 64-разрядных системах даже для астрономических дат (вроде 64-битового времени начала и завершения). Если вы устали ждать, когда же программа завершит свою работу, нажмите Control-C для ее завершения.

18.2. Использование таймеров

Таймер — это простое средство для указаний определенной точки в будущем, в которой должно произойти некоторое событие. Вместо того чтобы циклически запрашивать текущее время и проводить лишние растраты циклов центрального процессора, программа может отправить в ядро запрос на получение уведомления о том, что прошло определенное количество времени.

Существуют два способа применения таймеров: синхронный и асинхронный. Синхронное использование таймера возможно в единственном режиме — режиме ожидания (дожидаться истечения времени таймера). Асинхронная работа таймера, как и любого другого асинхронного устройства, сопровождается сигналами. Сюрпризом может оказаться то, что синхронный таймер может также вызывать сигналы.

18.2.1. Режим ожидания

Процесс, сопровождающийся запросом на невыполнение в течение определенного количества времени, называется отложенным (или "спящим"). Для режима ожидания доступны четыре функции; каждая из них измеряет время в различных единицах. Они также ведут себя и взаимодействуют с остальными частями системы по-разному.

unsigned int sleep(unsigned int seconds);

Функция sleep() вынуждает текущий процесс засыпать на время (в секундах), указанное параметром seconds, или до тех пор, пока процесс не получит сигнал, который он не может проигнорировать. На большинстве платформ функция sleep() реализуется в терминах сигнала SIGALRM, поэтому она не очень хорошо совмещается с системным вызовом alarm(), созданием обработчика SIGALRM, игнорированием сигнала SIGALRM, или применением интервальных таймеров (рассматриваются далее), которые разделяют один и тот же таймер и сигнал.

Если работа sleep() завершается раньше истечения полного выделенного времени, она возвращает количество оставшихся секунд. Если режим ожидания длился ровно столько, сколько запрашивалось, она возвращает ноль.