【问题标题】:how to define a loop to be run for some seconds/minutes long如何定义要运行几秒钟/几分钟的循环
【发布时间】:2014-10-18 00:12:46
【问题描述】:

我的目的是在定义的时间内执行while 循环(例如,本示例为 90 秒)。它不必精确到 90 秒,但 1-2 秒的误差是可以接受的。我确实为此目的使用了clock()`函数:

int main(void){
      clock_t start, end;
      volatile double elapsed;
      start = clock();
      int terminate = 1;
      while(terminate)
      {
              end = clock();
              elapsed = ((double) (end-start)) / (double) CLOCKS_PER_SEC *1000;
              printf("elapsed time:%f\n",elapsed);
              if(elapsed >= 90.0)
                        terminate = 0;
               usleep(50000);
       }
      printf("done..\n");
    return 0;
}

当我在笔记本电脑(x86、3.13 内核、gcc 4.8.2)上运行它时,我的秒表测量 72 秒 以完成它。 (在我的笔记本电脑上,elapsed 的秒精度需要 1000)

当我在 ARM 设备(armv5tejl、3.12 内核、gcc 4.6.3)上运行它时,完成代码需要 58 秒。 (我需要在 armv5 上的 elapsed 上使用 100)。

我在室温下运行代码,所以时钟应该是稳定的。我知道内核使线程休眠并且唤醒它们的时间不准确,等等。因此,正如我之前所说,我不希望得到一个完美的时机,但它应该有一定的准确性。

我曾尝试只使用usleep(甚至nanosleep),但分辨率也不好。最后,我提出了获取系统时间(小时、分钟、秒)的底部代码,然后计算经过的时间。它的工作精度很高。

我想知道是否有另一种使用成本更低的解决方案?

typedef struct{
    int hour;
    int minute;
    int second;
} timeInfo;

timeInfo getTimeInfo(void){
    timeInfo value2return;
    time_t rawtime;
    struct tm * timeinfo;
    time(&rawtime);
    timeinfo = localtime(&rawtime);
    value2return.hour = timeinfo->tm_hour;
    value2return.minute = timeinfo->tm_min;
    value2return.second = timeinfo->tm_sec;
    return value2return;
}

int checkElapsedTime(const timeInfo *Start, const timeInfo *Stop, const int Reference){
    if(Stop->hour < Start->hour){
        printf("1:%d\n", (Stop->hour +24) *3600 + Stop->minute *60 + Stop->second - (Start->hour *3600 +Start->minute * 60 + Start->second));
         if( ( (Stop->hour +24) *3600 + Stop->minute *60 + Stop->second - (Start->hour *3600 +Start->minute * 60 + Start->second)) >= Reference )
            return 0; //while(0): terminate the loop
         else
             return 1; //while(1)
    }else{
        printf("2:%d\n",Stop->hour *3600 + Stop->minute *60 + Stop->second - (Start->hour *3600 +Start->minute * 60 + Start->second));
        if( (Stop->hour *3600 + Stop->minute *60 + Stop->second - (Start->hour *3600 +Start->minute * 60 + Start->second)) >= Reference )
            return 0;
        else
            return 1;
    }
}

int main(void){

    timeInfo stop, start = getTimeInfo();
    int terminate = 1;
    while(terminate)
    {
        stop = getTimeInfo();
        terminate = checkElapsedTime(&start, &stop, 90);
        usleep(5000); //to decrease the CPU load
    }

    printf("terminated\n");

    return 0;
}

最后,我需要在 pthread 中运行它。

【问题讨论】:

    标签: c linux time clock time-t


    【解决方案1】:
    1. 使用time()clock()。编码目标是确定已用的挂墙时间,而不是使用的处理器时间。

      当前代码计算出进程经过的时间 * 1000 并将其与 90 秒进行比较。

      @uesp 暗示的clock() 返回“时钟函数确定使用的处理器时间。” C11dr §7.27.2.1 2.

      time() 返回“时间函数确定当前日历时间”§7.27.2.4 2

      difftime() 很好地找到了 2 个time_t 之间的差异(无论它们是什么单位/类型)并以秒为单位返回差异。

      int main(void) {
         time_t start, end;
         double elapsed;  // seconds
         start = time(NULL);
         int terminate = 1;
         while (terminate) {
           end = time(NULL);
           elapsed = difftime(end, start);
           if (elapsed >= 90.0 /* seconds */)
             terminate = 0;
           else  // No need to sleep when 90.0 seconds elapsed.
             usleep(50000);
         }
         printf("done..\n");
         return 0;
       }
      
    2. 次要:注意:使用clock()时,不需要* 1000。在运行 gcc 的基于 Windows 的机器上,对我来说,clock() 还返回了调用进程的 CPU 时间。

      elapsed = ((double) (end-start)) / (double) CLOCKS_PER_SEC *1000;
      elapsed = ((double) (end-start)) / CLOCKS_PER_SEC;
      
    3. 未成年人:不需要volatileelapsed 只是因为这个代码而改变。

      // volatile double elapsed;
      double elapsed;
      

    【讨论】:

      【解决方案2】:

      您的第一个版本似乎不起作用的原因是在 Linux 上 clock() 测量使用的 CPU 时间而不是实时时间(请参阅 here)。由于您正在休眠进程,因此实际时间和 CPU 时间不匹配。解决方案是像第二个示例一样检查实际时钟时间。

      请注意,在 Windows 上,clock() 确实为您提供了真正的时钟时间(请参阅 here)。

      【讨论】:

        【解决方案3】:

        使用alarm 并捕捉信号。信号处理程序将中断进程执行。你也可以试试pthread_cancel。单个运行时间 t 的循环或基于睡眠的方法可能会因时间 t 而变得不准确。如果循环是一个长时间运行的、紧凑的执行路径,那么休眠或中断根本无法解决您的问题。

        【讨论】:

          猜你喜欢
          • 2020-05-03
          • 2012-07-14
          • 2019-08-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-27
          • 2015-10-06
          相关资源
          最近更新 更多