c ++是clock_gettime()溢出?

时间:2012-05-13 14:34:51

标签: c++ time

当使用以下示例代码时,我认为tv_nsec值是循环的,因为它只是 long;

#include <iostream>
using namespace std;
#include <time.h>

int main(int argc, char *argv[]) {
  timespec time1, time2;
  timespec timens = {0};
  timens.tv_sec = 1;

  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1);
  nanosleep(&timens, (struct timespec *)NULL);
  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2);

  cout << time1.tv_nsec << " : " << time2.tv_nsec << endl;
  cout << (time2.tv_nsec-time1.tv_nsec) << endl;
  return 0;
}

$ ./microtime 
2754095 : 2766801
12706

开始和结束时间之间的差异是12706ns(12.7us),它不需要12us睡眠1秒,我合理确定!那么这里发生了什么,有没有tv_nsec循环?假设singed long给出较小范围的正值(0到2147483647)而不是unsigned long(0到4294967295),2147483647纳秒仍然只是超过2整秒!

如果我将代码更改为以下内容,我仍然会看到一个看似无效的输出;

timens.tv_sec = 0;
timens.tv_nsec = 100000;

$ ./microtime
2743552 : 2754327
10775

睡眠持续时间设定为100,000ns,但根据该输出,该程序已睡眠10,000ns。我知道这是一个很短的时间,但我试图在这里表明,无论是1秒钟还是像100us这样的短时间,这里似乎没有准确性,或者这些值之间的任何地方。我做错了什么,我是否以某种方式错误地实现了这个?为什么我不能在对clock_gettime()的调用之间得到事件的实际持续时间?

非常感谢你的时间。

更新

@Oli; 我可以使用以下代码测试您的建议,但它似乎不起作用:

int main(int argc, char *argv[]) {
  timespec time1, time2;
  timespec timens = {0};
  timens.tv_sec = 1;
  timens.tv_nsec = 0;

  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1);
  nanosleep(&timens, (struct timespec *)NULL);
  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2);

  cout <<time1.tv_sec<<"s:"<<time1.tv_nsec<<"ns : "<<
         time2.tv_sec<<"s:"<<time2.tv_nsec<<"ns"<<endl;
  cout <<(time2.tv_nsec-time1.tv_nsec)<<endl;
  return 0;
}

$ ./microtime
0s:2801478ns : 0s:2813732ns
12254

2 个答案:

答案 0 :(得分:4)

在计算时间间隔时,您还需要考虑tv_sec字段。

<强>更新

此外,CLOCK_PROCESS_CPUTIME_ID测量用于此过程的CPU时间。如果使用nanosleep得出,则此计时器不会递增。尝试例如而是CLOCK_MONOTONIC

答案 1 :(得分:2)

来自nano_sleep的手册:

  

未屏蔽的信号将导致nanosleep()提前终止睡眠,无论中断信号上的SA_RESTART值如何。

因此,您对nanosleep()的使用过于简单:
它应该看起来像这样(虽然这只是为了给你一个粗略的想法而进行测试)。

timespec requestedSleep = {0};
requestedSleep.tv_sec = 1;

timespec start = {0};
start = /* current real time */;

while( nanosleep(&requestedSleep, NULL) == -1)
{
    timespec end.t = {0};
    end = /* current real time */;

    updateRequestedSleepTime(requestedSleep, start, end);
    start = end;
}