Если вы посмотрите на функцию clock_gettime () , которая доступна во всех BSD и фактически определена как часть стандарта POSIX, вы увидите, что есть поддержка как минимум трех типов часы (многие системы поддерживают больше, чем эти часы, но на самом деле стандарт POSIX требует присутствия только одного, все остальные не обязательны):
CLOCK_REALTIME - POSIX требует, чтобы это присутствовало. Это настенные часы.
CLOCK_MONOTONIC - Понятия не имею, что это такое (и что означают секунды SI), но я понимаю, что эти часы никогда не будут прыгать назад, они могут только монотонно увеличиваться в значении.
CLOCK_UPTIME - Я не вижу, чем это отличается от CLOCK_MONOTONIC (время работы также никогда не переходит назад), но, по крайней мере, я знаю, что эти часы начинаются с нуля при загрузке ядра (тогда как не определено, какое начальное значение будет иметь CLOCK_MONOTONIC при загрузке ядра)
Давайте на секунду проигнорируем другие часы. CLOCK_REALTIME не гарантирует монотонного счета вверх, верно? Это фактическое «системное время». Я могу изменить системное время по желанию. Я могу установить его на 3 месяца в прошлом или на 5 лет в будущем, и каждый раз, когда моя система синхронизирует время с помощью NTP-сервера в сети, время может прыгать вперед или назад.
Теперь у нас есть две спящие функции в системе BSD. sleep () и nanosleep () . Я не уверен, но я ожидал бы, что sleep () будет реализован поверх nanosleep, в конце концов, я могу легко эмулировать sleep () с помощью nanosleep () и установить только количество секунд в struct timespec, сохраняя наносекунды равными нулю .
Я читал во многих источниках, что эти функции на самом деле работают, вычисляя время пробуждения (получить текущее время, добавить к нему количество сна), и затем система будет регулярно проверять, является ли текущее время позже , чем время пробуждения, и если это так, он снова проснется. Тот факт, что это проверяется только с интервалами, является причиной того, что на страницах руководства говорится, что текущий сон будет спать по меньшей мере такое количество времени (короче, только если он прерывается сигналом), но он может спать дольше (в зависимости от того, как часто система проверяет, истекло ли уже время пробуждения и зависит от того, сколько времени потребуется, прежде чем планировщик разрешит этому потоку снова работать).
Это все совершенно нормально для меня ... но есть один вопрос, который всегда беспокоил меня:
Согласно различным источникам, спящие (по крайней мере, наноспящие) используют CLOCK_REALTIME в качестве внутренних часов. Это означает, что если вы заставите nanosleep () спать в течение 30 секунд, а затем измените мои системные часы на 1 час в будущем, поток будет активирован почти сразу (1 час в будущем намного опережает время пробуждения Nanosleep ( ) рассчитано). Это тоже совершенно нормально. Однако что произойдет, если я скажу проснуться через 30 секунд, а затем пользователь узнает, что его системные часы опережают на один час, и переводит часы назад на один час? Тогда моя нить будет спать 1 час 30 секунд? Как это было бы довольно плохо.