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

发布于 2024-08-14 15:03:10 字数 184 浏览 3 评论 0原文

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

我需要一种可靠的方法来比较两个 timeval 结构。我尝试使用 timercmp(),但我的 gcc 版本不支持它,并且文档指出该函数不兼容 POSIX。

我应该怎么办?

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.

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.

What should I do?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

初相遇 2024-08-21 15:03:10

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)

timercmp() is just a macro 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))

If you need 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)
断舍离 2024-08-21 15:03:10

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

通常需要减去 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;
 }

googling timeval give this first result. From that page:

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.

 /* 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;
 }
蓝天白云 2024-08-21 15:03:10

这略有不同,但我认为清楚地说明了所涉及的逻辑。
我正在用 C 编写一些 MSP430 代码,并且有一个与 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;
}

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.

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;
}
哆兒滾 2024-08-21 15:03:10

为了查看时间间隔,我刚刚启动了这个。它返回一个 timeval 作为字符串,您可以打印或发送到文本文件:

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() 似乎工作不正常,所以我想要一种通过实际查看一些值来检查它的方法。

For viewing timevals I just whipped this up. It returns a timeval as a string that you can print or send to a text file:

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

Use like:

printf("nowtv: %s\n",tv2str(&nowtv));

nowtv: 1568407554.646623

Timercmp() didn't seem to work right so I wanted a way to check up on it by actually looking at some values.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文