2009-12-07 16 views
10

Ich schreibe ein Socket-Programm, das FIFO-Warteschlangen für zwei Eingabesockets verwaltet. Bei der Auswahl der zu wartenden Warteschlange ruft das Programm den letzten Zeitstempel aus jeder Warteschlange ab.Wie vergleiche ich zwei Zeitstempel in C?

Ich brauche eine zuverlässige Methode zum Vergleich zweier timeval Strukturen. Ich habe versucht, timercmp(), aber meine Version von GCC unterstützt es nicht, und die Dokumentation besagt, dass die Funktion nicht POSIX-kompatibel ist.

Was soll ich tun?

Antwort

5

googeln timeval geben this first result. Von dieser Seite:

Es ist oft notwendig, zwei Werte vom Typ struct timeval oder struct timespec zu subtrahieren. Hier ist der beste Weg, dies zu tun. Es funktioniert sogar auf einigen speziellen Betriebssystemen, wo das Element tv_sec einen vorzeichenlosen Typ hat.

/* Subtract the `struct timeval' values X and Y, 
    storing the result in RESULT. 
    Return 1 if the difference is negative, otherwise 0. */ 

int 
timeval_subtract (result, x, y) 
     struct timeval *result, *x, *y; 
{ 
    /* Perform the carry for the later subtraction by updating y. */ 
    if (x->tv_usec < y->tv_usec) { 
    int nsec = (y->tv_usec - x->tv_usec)/1000000 + 1; 
    y->tv_usec -= 1000000 * nsec; 
    y->tv_sec += nsec; 
    } 
    if (x->tv_usec - y->tv_usec > 1000000) { 
    int nsec = (x->tv_usec - y->tv_usec)/1000000; 
    y->tv_usec += 1000000 * nsec; 
    y->tv_sec -= nsec; 
    } 

    /* Compute the time remaining to wait. 
     tv_usec is certainly positive. */ 
    result->tv_sec = x->tv_sec - y->tv_sec; 
    result->tv_usec = x->tv_usec - y->tv_usec; 

    /* Return 1 if result is negative. */ 
    return x->tv_sec < y->tv_sec; 
} 
+1

Danke für den Tipp, aber ich benutze bereits den Code. In der Tat habe ich gerade realisiert, was mein Problem war. Vielen Dank für die Überprüfung von Google. Es ist wahrscheinlich das erste, was ich als Antwort gepostet hätte. =) –

+2

Um zu verdeutlichen, erkannte ich, dass die Zeitwerte initialisiert wurden, um 'tv_sec'- und' tv_usec'-Werte von 0 zu haben. Das 'itttimeofday()' zur korrekten Initialisierung der Warteschlangen behob das Problem. Danke für die Unterstützung. =) –

+0

2AShelly, ich würde hinzufügen, dass IMHO es besser ist, die zweite Bedingung folgendermaßen zu ändern: x-> tv_usec - y-> tv_usec> = 1000000', um die Zeit wie '5/1000000' in' 6 zu konvertieren/0'. – Kolyunya

11

timercmp() ist nur ein Makro in libc (sys/time.h):

# define timercmp(a, b, CMP)             \ 
    (((a)->tv_sec == (b)->tv_sec) ?            \ 
    ((a)->tv_usec CMP (b)->tv_usec) :           \ 
    ((a)->tv_sec CMP (b)->tv_sec)) 

Wenn Sie timersub(): klar

# define timersub(a, b, result)            \ 
    do {                  \ 
    (result)->tv_sec = (a)->tv_sec - (b)->tv_sec;        \ 
    (result)->tv_usec = (a)->tv_usec - (b)->tv_usec;       \ 
    if ((result)->tv_usec < 0) {            \ 
     --(result)->tv_sec;              \ 
     (result)->tv_usec += 1000000;           \ 
    }                   \ 
    } while (0) 
+0

Benötigt das Definieren des Makros _BSD_SOURCE, wenn unter Linux kompiliert wird. –

0

Das ist etwas anders, aber ich denke, veranschaulicht die involvierte Logik. Ich arbeite an einigen MSP430-Code in C, und habe eine Timestamp-Struktur sehr ähnlich wie timeval, aber mit nsecs anstelle von usecs.

Dieser Code hält alles positiv, so dass unsigned Ints würde gut funktionieren, und vermeidet Überläufe (denke ich). Es ändert auch nicht die Zeitstempel/Zeitspannen, die übergeben werden, außer dem Ergebnis natürlich.

typedef struct timestamp { 
    int32_t secs; 
    int32_t nsecs; 
} timestamp_t; 

int timestamp_sub(timestamp_t * x, timestamp_t * y, timestamp_t * result){ 
    // returns 1 if difference is negative, 0 otherwise 
    // result is the absolute value of the difference between x and y 
    negative = 0; 
    if(x->secs > y->secs){ 
     if(x->nsecs > y->nsecs){ 
      result->secs = x->secs - y->secs; 
      result->nsecs = x->nsecs - y->nsecs; 
     }else{ 
      result->secs = x->secs - y->secs - 1; 
      result->nsecs = (1000*1000*1000) - y->nsecs + x->nsecs; 
     } 
    }else{ 
     if(x->secs == y->secs){ 
      result->secs = 0; 
      if(x->nsecs > y->nsecs){ 
       result->nsecs = x->nsecs - y->nsecs; 
      }else{ 
       negative = 1; 
       result->nsecs = y->nsecs - x->nsecs; 
      } 
     }else{ 
      negative = 1; 
      if(x->nsecs > y->nsecs){ 
       result->secs = y->secs - x->secs - 1; 
       result->nsecs = (1000*1000*1000) - x->nsecs + y->nsecs; 
      }else{ 
       result->secs = y->secs - x->secs; 
       result->nsecs = y->nsecs - x->nsecs; 
      } 
     } 
    } 
    return negative; 
} 
+1

Sie verwenden lieber die Ganzzahl '1000000000' (oder' 1000 * 1000 * 1000', wenn Sie bevorzugen) und nicht den Gleitkommawert '1e9', da ersteres wahrscheinlich effizienter ist. –

Verwandte Themen