调用clock_gettime()时,返回的tv_nsec字段实际上可能超过一秒?

时间:2015-01-19 16:47:30

标签: c linux glibc libc

当您调用clock_gettime()时,它会返回timespec结构。

       struct timespec {
           time_t   tv_sec;        /* seconds */
           long     tv_nsec;       /* nanoseconds */
       };

我在手册页中找不到tv_nsec不会超过1秒的保证。实际存在保证吗?它可能依赖于linux的库(glibc?)实现吗?

关键的想法是:我是否需要规范化'来自clock_gettime()函数的任何结果?

3 个答案:

答案 0 :(得分:6)

根据opengroup

  

tv_nsec成员仅在大于或等于零时有效,并且   小于一秒钟内的纳秒数(1000万)。该   这种结构描述的时间间隔是(tv_sec * 10' - 。4m'9'.4m'   + tv_nsec)纳秒。

所以根据opengroup的说法,看起来它必须不到1秒。

答案 1 :(得分:2)

我相当肯定答案永远是"不"。

clock_gettime赢回了tv_nsec> = 10e9。 clock_settime()和clock_nanosleep()都将这个限制放在他们的输入上,所以我总是假设clock_gettime与之一致。

同样在Linux + glibc上,如果你深入了解glibc,你会看到这样的代码:

摘自glibc / nptl / pthread_clock_gettime.c:

/* Compute the seconds.  */
tp->tv_sec = tsc / freq;

/* And the nanoseconds.  This computation should be stable until
   we get machines with about 16GHz frequency.  */
tp->tv_nsec = ((tsc % freq) * 1000000000ull) / freq;

这也发生在glibc / sysdeps / unix / clock_gettime.c中。

但你是对的,这个手册页不能说。至少不是我的Linux发行版或opengroup.org上的内容。因此,实施在技术上可以随着警告的变化而​​变化。

如果你正在为Linux + glibc写作,我说你的保险箱。您可以自己检查备用开源libc库,例如Android的仿生,或缩小的newlib。

如果您针对某些其他封闭源POSIX系统,您或您的客户在支付费用时遇到问题,请询问供应商是否未记录。

如果试图尽可能地移植并感到偏执,请使用"标准化"来包装clock_gettime。功能如下:

int my_gettime( struct timespec * ts ) 
{  
   int ret; 
   if( 0 == (ret = clock_gettime(SOME_CLOCK, ts))
   {
      while (tv_nsec >= 1000000000 )
      {
         ts->tv_nsec -= 1000000000;
         ts->tv_sec += 1;
      }
   }
   return ret;
}

答案 2 :(得分:1)

不,您不需要对结果进行标准化。您可以信任纳秒字段在0和999999999之间,包括在内。

clock_gettime()的POSIX规范明确规定如果clock_settime() EINVAL tv_nsec < 0 || tv_nsec >= 1000000000将失败。

标准学者可能会争论,但仅仅简单的对称性告诉我们,我们可以从clock_gettime()得到相同的结论。从技术上讲,100000000 ns是一秒,由于标准始终使用术语“秒和纳秒”,逻辑结论是纳秒字段应该被标准化。此外,如果clock_gettime()以纳秒字段超出范围返回结果,很多程序将以有趣且引人入胜的方式出现故障。