Czy mógłby pan wyjaśnić różnicę między CLOCK_REALTIME
i CLOCK_MONOTONIC
zegary zwracane przez clock_gettime()
Linux?
Który jest lepszy wybór, jeśli muszę obliczyć upływ czasu między znacznikami czasu wytworzonymi przez źródło zewnętrzne a bieżącym czasem?
Wreszcie, jeśli mam demona NTP okresowo dostosowującego czas systemowy, w jaki sposób te dostosowania oddziałują z każdym z nich CLOCK_REALTIME
i CLOCK_MONOTONIC
?
CLOCK_MONOTONIC
najlepszy wybór w tym scenariuszu? np. Patriot Missile SystemKsiążka Roberta Love'a LINUX System Programming 2nd Edition , szczególnie odnosi się do twojego pytania na początku rozdziału 11, str. 363:
To powiedziawszy, uważam, że zakłada, że procesy działają na tej samej instancji systemu operacyjnego, więc możesz chcieć mieć okresową kalibrację, aby móc oszacować dryft.
źródło
CLOCK_REALTIME
ma wpływ NTP i może poruszać się do przodu i do tyłu.CLOCK_MONOTONIC
nie jest i przesuwa się o jeden tik na tyknięcie.źródło
System.nanoTime()
używaCLOCK_MONOTONIC
i może mierzyć czas trwania 1000ns lub mniej. Może myślisz o czasie systemowym, który czasem ogranicza się do milisekund?Oprócz odpowiedzi Ignacio ,
CLOCK_REALTIME
może skakać do przodu, a czasami do tyłu.CLOCK_MONOTONIC
nie robi ani; po prostu idzie naprzód (chociaż prawdopodobnie resetuje się przy ponownym uruchomieniu).Solidna aplikacja musi być w stanie tolerować
CLOCK_REALTIME
przeskakiwanie do przodu od czasu do czasu (i być może bardzo nieznacznie do tyłu bardzo rzadko, chociaż jest to raczej przypadek na krawędzi).Wyobraź sobie, co dzieje się, gdy zawieszasz laptopa -
CLOCK_REALTIME
przeskakuje do przodu po wznowieniu,CLOCK_MONOTONIC
nie robi tego. Wypróbuj na maszynie wirtualnej.źródło
CLOCK_PROCESS_CPUTIME_ID
. Szybki test:$ perl -w -MTime::HiRes=clock_gettime,CLOCK_MONOTONIC -E 'say clock_gettime(CLOCK_MONOTONIC)'
-> 706724.117565279. Liczba ta odpowiada czasowi pracy systemu w Linuksie, ale standard mówi, że jest arbitralny.CLOCK_MONOTONIC
zatrzymywanie się po zawieszeniu / wznowieniu było zgodne z POSIX. Powinien to być czas od ustalonego punktu w przeszłości, ale zatrzymanie zegara przed zawieszeniem / wznowieniem to przerywa.Cytaty POSIX 7
POSIX 7 określa oba na stronie http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html :
CLOCK_REALTIME
:CLOCK_MONOTONIC
(funkcja opcjonalna):clock_settime()
daje ważną wskazówkę: systemy POSIX są w stanie dowolnie sięCLOCK_REALITME
z tym zmieniać , więc nie polegaj na tym, że płynie ani w sposób ciągły, ani do przodu. NTP może być zaimplementowany przy użyciuclock_settime()
i może tylko wpływaćCLOCK_REALITME
.Implementacja jądra Linuksa wydaje się wymagać czasu rozruchu jako epoki dla
CLOCK_MONOTONIC
: Punkt wyjścia dla CLOCK_MONOTONICźródło
Przepraszamy, brak reputacji, aby dodać to jako komentarz. Jest to więc odpowiedź uzupełniająca.
W zależności od tego, jak często będziesz dzwonić
clock_gettime()
, powinieneś pamiętać, że tylko niektóre „zegary” są dostarczane przez Linux w VDSO (tj. Nie wymagają wywołania systemowego z całym narzutem jednego - co pogorszyło się dopiero po dodaniu Linuksa obrony przed atakami typu Widm).Chociaż
clock_gettime(CLOCK_MONOTONIC,...)
,clock_gettime(CLOCK_REALTIME,...)
igettimeofday()
zawsze będą bardzo szybkie (przyspieszane przez VDSO), nie jest to prawdą, na przykład dla CLOCK_MONOTONIC_RAW lub jakiegokolwiek innego zegara POSIX.Można to zmienić w zależności od wersji jądra i architektury.
Chociaż większość programów nie musi zwracać na to uwagi, mogą występować skoki opóźnienia w zegarach przyspieszanych przez VDSO: jeśli trafisz je dokładnie, gdy jądro aktualizuje obszar pamięci współużytkowanej z licznikami zegarów, musi poczekać na jądro do końca.
Oto „dowód” (GitHub, aby trzymać boty z dala od kernel.org): https://github.com/torvalds/linux/commit/2aae950b21e4bc789d1fc6668faf67e8748300b7
źródło