Вдохновленный последней секундой прыжка, я изучал тайминги (в частности, интервальные таймеры), используя вызовы POSIX.
POSIX предлагает несколько способов настройки таймеров, но все они проблематичны:
-
sleep
иnanosleep
- это раздражает перезапуск после того, как они прерываются сигналом, и они вводят перекос часов. Вы можете избежать некоторых, но не всех, этого перекоса с некоторой дополнительной работой, но эти функции используют часы реального времени, поэтому это не лишено недостатков. -
setitimer
или более современныеtimer_settime
-это предназначены для интервальных таймеров, но они предназначены для каждого процесса, что является проблемой, если вам нужно несколько активных таймеров. Они также не могут использоваться синхронно, но это менее важно. -
clock_gettime
иclock_nanosleep
кажутся правильным ответом при использовании сCLOCK_MONOTONIC
.clock_nanosleep
поддерживает абсолютные таймауты, поэтому вы можете просто спать, увеличивать время ожидания и повторять. Это легко перезапустить и после перерыва. К сожалению, эти функции также могут быть специфичными для Linux: нет поддержки для них в Mac OS X или FreeBSD. -
pthread_cond_timedwait
доступен на Mac и может работать сgettimeofday
как временное решение, но на Mac он может работать только с часами реального времени, поэтому он подвержен неправильному поведению, когда установлены системные часы или скачок второй происходит.
Есть ли API, который мне не хватает? Есть ли разумно переносимый способ создания корректных интервальных таймеров в UNIX-подобных системах или это суммирует сегодняшнее состояние?
Хорошо себя вести и разумно переносить, я имею в виду:
- Не склонен к перекосу часов (минус, конечно, собственный косой сигнал системы)
- Устойчив к установленным системным часам или появлению второй секунды
- Возможность поддержки нескольких таймеров в одном процессе
- Доступно, по крайней мере, для Linux, Mac OS X и FreeBSD.
Заметка о прыжках секунд (в ответ на R.. answer):
Дни POSIX составляют ровно 86 400 секунд, но дни реального мира редко могут быть длиннее или короче. Как система разрешает это несоответствие, определяется реализацией, но обычно для второго прыжка используется одна и та же временная метка UNIX, как и предыдущая секунда. См. Также: Секундомер и что с ним делать.
Ошибка второго ядра Linux в ярости была результатом неудачной работы после установки часов назад: https://lkml.org/lkml/2012/7/1/203. Даже без этой ошибки часы бы отскочили назад на одну секунду.