2011-01-26 17 views
22

Oto mały test, który napisałem, aby sprawdzić, czy czas rzeczywiście działa tylko w Linuksie.Jak zatrzymać czas przed uruchomieniem w systemie Linux?

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

bool timeGoesForwardTest2() 
{ 
    timeval tv1, tv2; 
    double startTime = getTimeSeconds(); // my function 

    while (getTimeSeconds() - startTime < 5) 
    { 
     gettimeofday(&tv1, NULL); 
     gettimeofday(&tv2, NULL); 

     if (tv2.tv_usec == tv1.tv_usec && 
      tv2.tv_sec == tv1.tv_sec) 
     { 
     continue; // Equal times are allowed. 
     } 

     // tv2 should be greater than tv1 
     if (!(tv2.tv_usec>tv1.tv_usec || 
       tv2.tv_sec-1 == tv1.tv_sec)) 
     { 
     printf("tv1: %d %d\n", int(tv1.tv_sec), int(tv1.tv_usec)); 
     printf("tv2: %d %d\n", int(tv2.tv_sec), int(tv2.tv_usec)); 
     return false; 
     }   
    } 
    return true; 
} 

Test kończy się niepowodzeniem z wynikiem.

tv1: 1296011067 632550 
tv2: 1296011067 632549 

ummm ....

Dlaczego tak się dzieje?

Oto moja konfiguracja:

Linux version 2.6.35-22-generic ([email protected]) (gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu4)) #33-Ubuntu SMP Sun Sep 19 20:34:50 UTC 2010 (Ubuntu 2.6.35-22.33-generic 2.6.35.4) 
... running inside VirtualBox 3.2.12, in Windows 7. 
+1

Może to mieć związek z maszyną wirtualną. Czy próbowałeś tego z rzeczywistą instalacją Linuksa? –

+0

Upewnij się, że sprawdzasz całkowite przejście na tv_sec i tv_usec, gdy robisz z nimi jakiekolwiek obliczenia. –

+26

Podejrzewam, że to dlatego, że połączenia czasowe wychodzą na dwa różne rdzenie procesora, a jeden z nich znajduje się w pobliżu miniaturowej czarnej dziury.Wyjdź z domu. Tak szybko, jak to możliwe. Poważnie! – paxdiablo

Odpowiedz

17

Istnieje open issue at the VirtualBox Bug Tracker. odwołują się one do blogu stwierdzając, dlaczego you shouldn't use gettimeofday() mierzyć upływ czasu:

Najbardziej przenośny sposobem pomiaru czasu prawidłowo wydaje się być clock_gettime (CLOCK_MONOTONIC, ...)

+1

Link do bugtrackera wskazuje również, że 'CLOCK_MONOTONIC' wykazuje ten sam problem - podobnie jak FreeBSD działający pod VirtualBox. Wygląda na to, że jest błędem VirtualBox. – caf

+0

Czas na maszyny wirtualne wydaje się być całkiem owocowy. Moja instalacja VMWare w pracy nagle zdecydowała, że ​​będzie miała czas na 1/2 prawidłowej stawki. –

+0

To wydaje się mieć rację. gettimeofday jest dla mnie problematyczny na maszynach natywnych i wirtualnych. clock_gettime również wydaje się nie działać dla VirtualBox. Błąd w VirtualBox. – user48956

5

To nie jest tak, że to działa wstecz. Lepiej powiedzieć, że nie zgłasza prawidłowej godziny. Dzieje się tak dlatego, że komputery, bez pomocy dedykowanego podsystemu czasowego, po prostu nie są w stanie precyzyjnie raportować czasu w odstępach milisekundowych.

Precyzja zależy od sprzętu, systemu operacyjnego, a nawet od zasilania. Oto article for starters. Trochę stary, ale ładnie przekazuje ten pomysł.

+0

Ta odpowiedź jest nonsensem. Każdy nowoczesny system podobny do systemu Unix zapewnia dokładność do 10 milisekund lub wyższą, a rozdzielczość nanosekundowa nie jest niczym niezwykłym. Słyszałem, że system Windows nie działa źle ... –

+0

@R: Myślałem o liniach starych timerów przerwań systemu Windows, kiedy zacytowałem oryginalną rozdzielczość. Zaktualizowano moją odpowiedź na współczesne czasy ... –

10

Liczniki czasu maszyn na większości maszyn mają tylko około 15 precyzji użycia (nawet w przypadku kodu natywnego). Czas płynący "w tył" jest dziwny, ale tak naprawdę nie można polegać na tym poziomie (1 usec). (Uwaga: istnieje różnica między precyzją a dokładnością, dokładność większości timerów jest gorsza niż precyzja). Użycie maszyny wirtualnej może również pogorszyć sytuację.

Aktualizacja: Typo

+0

Świetny punkt dotyczący precyzji i dokładności. Przykład: RDTSC ma ekstremalną precyzję (sub-nanosekundę na wielu nowoczesnych maszynach), ale potencjalnie znacznie gorszą dokładność niż jakiekolwiek normalne funkcje pomiaru czasu. – ephemient

30

gettimeofday() nie gwarantuje się monotonna. Użyj clock_gettime(CLOCK_MONOTONIC), jeśli potrzebujesz tej gwarancji.

+0

To prawda, ale link do bugtrackera opublikowany przez @ vz0 mówi, że ten sam problem występuje w VirtualBox z "CLOCK_MONOTONIC", więc jest tu również błąd. – caf

1

Czas nie powinien działać wstecz na prawdziwym sprzęcie; na maszynie wirtualnej twój przebieg może się różnić.

W każdym przypadku Twoja aplikacja prawdopodobnie nie powinna zakładać, że czas nie działa wstecz przez bardzo małą ilość (myśl, może przez 1 sekundę).

Tak, clock_gettime jest dobry, ale nawet ten może uruchomić wstecz w przypadku wadliwego sprzętu (lub VM, jak w przykładzie).

Widziałem błąd sprzętowy powodujący, że czas działa wstecz (choć bardzo rzadko), był przyczyną pewnych bardzo osobliwych problemów.

W szczególności wszystko, co wiąże się ze porównywaniem sygnatur czasowych pliku, ulegnie awarii, gdy czas się cofnie.

Powiązane problemy