Zaman neden time () tarafından bazen C kodunda timespec_get () öğesinin saniye bileşeninin 1 saniye gerisindedir?


12

Aşağıdaki kod snippet'i:

struct timespec ts;
for (int x = 0; x < 100000000; x++) {
    timespec_get(&ts, TIME_UTC);
    long cTime = (long) time(NULL);
    if (cTime != ts.tv_sec && ts.tv_nsec < 3000000) {
        printf("cTime: %ld\n", cTime);
        printf("ts.tv_sec: %ld\n", ts.tv_sec);
        printf("ts.tv_nsec: %ld\n", ts.tv_nsec);
    }
}

bu çıktıyı üretir:

...
cTime: 1579268059
ts.tv_sec: 1579268060
ts.tv_nsec: 2527419
cTime: 1579268059
ts.tv_sec: 1579268060
ts.tv_nsec: 2534036
cTime: 1579268059
ts.tv_sec: 1579268060
ts.tv_nsec: 2540359
cTime: 1579268059
ts.tv_sec: 1579268060
ts.tv_nsec: 2547039
...

Neden arasındaki tutarsızlık cTimeve ts.tv_sec? Koşullu olarak değiştirilirse sorunun oluşmadığını unutmayın ts.tv_nsec >= 3000000. Sorun nanosaniyenin 3000000'den küçük olmasına bağlıdır.


Kullanılan işletim sistemi, sürümü, kullanılan C kütüphanesinin sürümü hakkında daha spesifik olmanız gerekir.
Bazı programcı dostum

2
Bazı programgramdudu Linux Debian 8, GCC 6.3.0.
Theo d'Or

Nedir timespec_get()? Bu C veya C ++ mı? Görünüşe göre std::timespec_get. Lütfen uygun etiketi kullanın.
Marco Bonelli

MarcoBonelli: C11'de C'ye eklendi. Çevrimiçi çoğaltabilir .
ShadowRanger

@ShadowRanger referans için teşekkür ederim, sistemim maniçin bir giriş göremedim, timespec_getbu yüzden sonuçlara atladım. Mantıklı.
Marco Bonelli

Yanıtlar:


11

Bunun nedeni, (dolaylı olarak) farklı sistem saatlerini kullanmanızdır. timespec_get()kullandığı yüksek çözünürlüklü iken, sistem çapında gerçek zamanlı saat time()kullanımları kaba gerçek zamanlı saat.

Kullanmaya çalışmak

clock_gettime(CLOCK_REALTIME_COARSE, &ts);

senin yerine timespec_get(), o zaman fark yok olmalıdır.

Düzenle:

Bu , vclock_gettime.c adlı Linux Çekirdek Kaynağı'nda görülebilir.

Gerçekten de burada görmek biraz incelikli. Yapı elemanlarının saniye bölümü, aynı değerleri kullanır CLOCK_REALTIME_COARSEve CLOCK_REALTIMEaynı değerleri içerir, ancak nanosaniye bölümü farklıdır; ile CLOCK_REALTIMEdaha büyük olabilir 1000000000(ki bu bir saniyedir). Bu durumda, çağrı üzerine sabitlenir:

ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
ts->tv_nsec = ns;

Bu düzeltme ne ile CLOCK_REALTIME_COARSEne de ile yapılır time(). Bu arasındaki farkı açıklar CLOCK_REALTIMEve time().


Bu herhangi bir yerde belgeleniyor mu, yoksa time(muhtemelen) daha performanslı ama daha az doğru saatle (sadece ikinci ayrıntıya sahip olduğu teorisinde, kimin hassasiyete ihtiyaç duyduğu)? Sanırım gerçek zamanlı bir milisaniye kadar gecikme (çevrimiçi testler, bir ms üzerinde zaman zaman gecikme gösterdi, ancak çok fazla değil), sanırım sadece ikinci ayrıntı düzeyini sorarsanız.
ShadowRanger

@ShadowRanger Daha fazla ayrıntı ekledim
Ctx

Niyetin açık bir şekilde belgelenmesi değil, ancak bu bir oylama için yeterli ayrıntı. :-) Saatin aslında bir saniyeden fazla ek nanosaniyeden fazla rapor edebileceği komik.
ShadowRanger

@ShadowRanger Bunun için kaynak dışında gerçek bir belge bulamadım, bu da davranışın önceden haber verilmeksizin ayrıntılı olarak değişebileceği anlamına geliyor
Ctx

@Ctx Ayrıntılı cevap için teşekkür ederim! Timespec_get (), POSIX yerine C11 olduğundan ve hangi saatin kullanılacağını gerektirmediğinden, tavsiye ettiğiniz clock_gettime () yerine timespec_get () kullanacağım. Farklı saatlerin kullanıldığı hakkında hiçbir fikrim yoktu, ancak seçim göz önüne alındığında, kaba saati kullanmanın fazla bir anlamı göremiyorum.
Theo d'Or
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.