2

我需要使用函数 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 以将其转换为纳秒。

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

我通读了整个手册页,但找不到原因,如果有的话,希望能得到解释。

4

3 回答 3

1

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

于 2020-03-30T14:27:28.777 回答
1

保存自 Unix 纪元以来的tv_sec完整秒数 - 1970-01-01 00:00:00 +00:00 - 并且tv_usec(或tv_nsec使用更现代的struct timespec)保存小数部分 - 值 [0..999,999]微秒struct timeval和 [0..999,999,999] 纳秒struct timespec.

在 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从值派生的time_t。他们的算术并不难。

我注意到,在某些方面,POSIX 未对两者struct timeval进行struct timespec指定。tv_useca 的或tv_nsec部分的符号是什么,struct timeval或者组件struct timespec是否tv_sec为负(请参阅自纪元以来的秒数-如果年份 <1970 或值为负,则关系未定义)。POSIX 保留了未定义的负值的行为tv_sec,这可能是明智的,但确实让生活有点困难。当然,还有“儒略历和公历是哪个国家的哪个部分什么时候切换的”的问题。和“有零年吗?” 这也必须处理。什么时候time_t是一个 32 位的数字,它可以追溯到 1901 年 12 月,这在很大程度上避免了这些问题(但俄罗斯直到十月革命之后才从儒略转换为公历,这发生在公历 11 月)。现在这time_t通常是一个 64 位数字,公元前(或 BCE)年也变得可表示。

tv_usec打印或tv_nsec部分时要小心。%.6d请记住通过使用微秒、纳秒来添加足够的前导零%.9ld,其中必要的转换说明符(dvs ldvs ...)tv_usec在 POSIX 中没有明确定义——但d通常是正确的。(tv_nsec成员是long; 这很容易和可靠。)

于 2020-03-30T17:22:56.173 回答
0

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

于 2020-03-30T14:28:27.640 回答