Как сравнить две метки времени в C?
Я пишу программу сокетов, которая поддерживает очереди FIFO для двух входных сокетов. При принятии решения, какую очередь обслуживать, программа извлекает самую последнюю отметку времени из каждой очереди.
Мне нужен надежный метод для сравнения двух timeval
Структуры. Я пытался с помощью timercmp()
, но моя версия gcc не поддерживает ее, и в документации говорится, что эта функция не POSIX-совместима.
Что я должен делать?
3 ответа
Прибегая к помощи timeval
дать этот первый результат. С этой страницы:
Часто бывает необходимо вычесть два значения типа struct timeval или struct timespec. Вот лучший способ сделать это. Он работает даже в некоторых специфических операционных системах, где член tv_sec имеет тип unsigned.
/* 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;
}
timercmp()
это просто макрос в 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))
Если тебе надо timersub()
:
# 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)
Это немного отличается, но я думаю, что ясно иллюстрирует логику. Я работаю над кодом MSP430 на C, и у меня есть структура меток времени, очень похожая на timeval, но с nsecs вместо usecs.
Этот код сохраняет все положительное, поэтому беззнаковые целочисленные значения будут работать нормально и избегают переполнений (я думаю). Он также не изменяет передаваемые временные метки / временные интервалы, кроме результата, конечно.
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;
}
Я просто придумал это для просмотра временных интервалов. Он возвращает значение времени в виде строки, которую вы можете распечатать или отправить в текстовый файл:
char *tv2str(struct timeval *intv) {
static char ans[200];
snprintf(ans,200,"%u.%u",(unsigned int)intv->tv_sec, \
(unsigned int) intv->tv_usec);
return ans;
}
Используйте как:
printf("nowtv: %s\n",tv2str(&nowtv));
nowtv: 1568407554.646623
Похоже, что Timercmp() работает неправильно, поэтому я хотел проверить это, взглянув на некоторые значения.