【问题标题】:gettimeofday() - Why use both seconds and microseconds?gettimeofday() - 为什么同时使用秒和微秒?
【发布时间】:2020-03-30 14:22:38
【问题描述】:

我需要使用函数 gettimeofday 来完成家庭作业,在阅读了手册页并查看了一些在线示例之后,我不明白为什么人们有时会同时使用结构的 tv_sec 成员和结构的 tv_usec 成员。 手册页指出:

  The tv argument is a struct timeval (as specified in <sys/time.h>):

       struct timeval {
           time_t      tv_sec;     /* seconds */
           suseconds_t tv_usec;    /* microseconds */
       };

所以,假设我需要以纳秒为单位返回时间,并且我创建了两个 timeval 结构,start 和 end,并且我使用 gettimeofday() 记录了它们的时间。 当然,我的第一个想法是计算微秒的差异,即 start.tv_usec-end.tv_usec 然后将其乘以 1000 以将其转换为纳秒。

但是,许多在线示例和教程都会计算秒和微秒的差异,然后将它们转换然后相加。 (e.g.)

我通读了整个手册页,但找不到原因,如果有任何解释,我将不胜感激。

【问题讨论】:

  • gettimeofday() 已被 posix 弃用,顺便说一句。请改用clock_gettime(),尤其是如果您需要纳秒。
  • 或者,因为它被标记为 C++ 而不是 C,所以使用 std::chrono::high_resolution_clock
  • std::chrono::steady_clock,如果时间可能倒退是一个问题。

标签: c++ c linux manpage gettimeofday


【解决方案1】:

“微秒”字段没有足够的空间来存储过去的所有时间。 “秒”字段不够精确。它们共同提供了最多的信息。

【讨论】:

    【解决方案2】:

    tv_sec 保存自 Unix 纪元(1970-01-01 00:00:00 +00:00)以来的秒数,tv_usec(或tv_nsec,当使用更现代的@ 987654327@) 保存小数部分——struct timeval 的值为 [0..999,999] 微秒,struct timespec 的值为 [0..999,999,999] 纳秒。

    在 64 位整数普及之前的日子里,time_t 是一个 32 位有符号类型,并且在 2038 年 1 月“用完”——自那个纪元以来将有 20 亿秒。没有空间将亚秒单位存储在一个整数中。

    -2147483647 = 1901-12-13 20:45:53 +00:00
    +2147483647 = 2038-01-19 03:14:07 +00:00
    

    即使是现在,如果处理纳秒,您需要 30 位来表示最多 999,999,999 纳秒(以及 20 位来表示最多 999,999 微秒)。纳秒的要求意味着尝试缩放 64 位数字来表示秒和纳秒是不明智的——Y2K38 问题将推迟大约 280 年,而两部分解决方案将其推迟到宇宙结束之后,对于每个人来说应该足够长。 (如果我还在的话,我计划在 5000-01-02 开始研究 Y10K 问题。?)

    因此,虽然不理想,但两部分结构使使用采用 time_t 值的常规格式化函数变得容易——它们有很多,而采用 struct tm 的那些函数派生自 @987654334 @ 价值。而且它们的算术并不难。

    我注意到,在某些方面,struct timevalstruct timespec 都没有被 POSIX 指定。如果tv_sec 组件为负数,则struct timevalstruct timespectv_usectv_nsec 部分的符号是什么(请参阅Seconds Since the Epoch如果年份是)。 POSIX 未定义 tv_sec 的负值行为,这可能是明智的,但确实让生活有点困难。当然,还有“儒略历和公历是哪个国家的哪个部分什么时候切换的”的问题。和“有零年吗?”这也必须处理。当time_t 是一个 32 位数字时,它可以追溯到 1901 年 12 月,这在很大程度上避免了这些问题(但俄罗斯直到十月革命之后才从儒略转换为公历,十月革命发生在公历的 11 月)。既然time_t 通常是一个 64 位数字,那么公元前(或 BCE)年也可以表示了。

    打印tv_usectv_nsec 部分时要小心。请记住通过使用%.6d 为微秒添加足够的前导零,%.9ld 用于纳秒,其中tv_usec 的必要转换说明符(tv_usec 与 ...)在 POSIX 中没有明确定义 - 但@987654352 @ 通常是正确的。 (tv_nsec 成员是 long;这既简单又可靠。)

    【讨论】:

      【解决方案3】:

      时间用整数表示,加上 0 - 999999 范围内的微秒。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-05
        • 2014-05-19
        • 2013-01-12
        • 1970-01-01
        • 2011-02-04
        • 2013-08-23
        • 1970-01-01
        相关资源
        最近更新 更多