如何比较C中的两个时间戳?

时间:2022-03-10 23:56:43

I'm writing a socket program that maintains FIFO queues for two input sockets. When deciding which queue to service, the program pulls the most recent time-stamp from each queue.

我正在编写一个套接字程序来维护两个输入套接字的FIFO队列。在决定要服务的队列时,程序从每个队列中提取最新的时间戳。

I need a reliable method for comparing two timeval structs. I tried using timercmp(), but my version of gcc doesn't support it, and documentation states that the function is not POSIX compliant.

我需要一种可靠的方法来比较两个时间结构。我尝试使用timercmp(),但我的gcc版本不支持它,并且文档声明该函数不符合POSIX。

What should I do?

我该怎么办?

3 个解决方案

#1


5  

googling timeval give this first result. From that page:

谷歌搜索timeval给出了第一个结果。从那个页面:

It is often necessary to subtract two values of type struct timeval or struct timespec. Here is the best way to do this. It works even on some peculiar operating systems where the tv_sec member has an unsigned type.

通常需要减去struct timeval或struct timespec类型的两个值。这是最好的方法。它甚至可以在某些特殊的操作系统上运行,其中tv_sec成员具有无符号类型。

 /* 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;
 }

#2


11  

timercmp() is just a macro in libc (sys/time.h):

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))

If you need timersub():

如果你需要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)

#3


0  

This is slightly different, but I think clearly illustrates the logic involved. I'm working on some MSP430 code in C, and have a timestamp struct very similar to timeval, but with nsecs instead of usecs.

这略有不同,但我认为清楚地说明了所涉及的逻辑。我正在使用C语言编写一些MSP430代码,并且时间戳结构与timeval非常相似,但是使用nsecs而不是usecs。

This code keeps everything positive, so unsigned ints would work fine, and avoids overflows (I think). It also doesn't modify the timestamps/timevals being passed in, except the result of course.

这段代码保持一切正面,因此无符号整数可以正常工作,并避免溢出(我认为)。除了结果之外,它也不会修改传入的时间戳/时间。

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


5  

googling timeval give this first result. From that page:

谷歌搜索timeval给出了第一个结果。从那个页面:

It is often necessary to subtract two values of type struct timeval or struct timespec. Here is the best way to do this. It works even on some peculiar operating systems where the tv_sec member has an unsigned type.

通常需要减去struct timeval或struct timespec类型的两个值。这是最好的方法。它甚至可以在某些特殊的操作系统上运行,其中tv_sec成员具有无符号类型。

 /* 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;
 }

#2


11  

timercmp() is just a macro in libc (sys/time.h):

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))

If you need timersub():

如果你需要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)

#3


0  

This is slightly different, but I think clearly illustrates the logic involved. I'm working on some MSP430 code in C, and have a timestamp struct very similar to timeval, but with nsecs instead of usecs.

这略有不同,但我认为清楚地说明了所涉及的逻辑。我正在使用C语言编写一些MSP430代码,并且时间戳结构与timeval非常相似,但是使用nsecs而不是usecs。

This code keeps everything positive, so unsigned ints would work fine, and avoids overflows (I think). It also doesn't modify the timestamps/timevals being passed in, except the result of course.

这段代码保持一切正面,因此无符号整数可以正常工作,并避免溢出(我认为)。除了结果之外,它也不会修改传入的时间戳/时间。

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;
}