【问题标题】:run a piece of code at regular interval without using sleep在不使用睡眠的情况下定期运行一段代码
【发布时间】:2015-12-29 11:00:19
【问题描述】:

我有一个函数,它会在特定的时间间隔被调用。我需要检查以前调用的时间和当前时间。如果函数调用之间的差异是 10 毫秒,则执行一些代码。不应使用睡眠,因为其他一些事情正在并行执行。我编写了以下代码,该函数每 10 毫秒调用一次,但我计算的差异有时会少 1 或 2 毫秒。计算差异的最佳方法是什么?

fxn()
{
    int logCurTime;
    static int logPrevTime = 0, logDiffTime = 0;
    getCurrentTimeInMilliSec(&logCurTime);          

    if (logPrevTime > 0)
        logDiffTime += logCurTime - logPrevTime;

    if (logCurTime <= logPrevTime)
        return;

    if (logDiffTime >= 10)
    {
        ...
        ...
        logDiffTime = 0;
    }
    logPrevTime = logCurTime;
}

例如: fxn 以 10 毫秒的间隔被调用 10 次。一些实例 logDiffTime 只是 8 或 9,而下一个实例则考虑剩余时间。即 11 或 12。

【问题讨论】:

  • 你不能使用 alarm() 并设置期望周期的计时器吗?使用你的函数作为警报处理程序。
  • "事物是并行执行的" - 如果是这样,为什么不使用睡眠?
  • @StefanFalk - 在该函数内部,我将有另一个条件以每 20 秒执行一次 f 代码。所以如果我使用睡眠,那么其他条件会影响
  • 建议的答案都没有解决 Windows。
  • 1 到 2 毫秒的差异完全在正常操作系统上的抖动范围内。当操作系统决定暂时做其他事情时,预计有时会达到几百毫秒。在您迁移到实时操作系统之前,您无法预测到 10 毫秒。

标签: c linux windows


【解决方案1】:

使用sleep() 让代码在特定时间间隔内执行确实是个坏主意。将您的函数注册为定时器中断的处理程序。然后它会非常准时地被调用。

如果你在你的函数中做繁重的工作,那么你应该在另一个线程中做,因为当你的函数花费太长时间时你会遇到麻烦。 (它将再次从头开始调用)。

在 posix (linux) 中你可以这样做

#include <sys/time.h>
#include <stdio.h>
#include <signal.h>

if (signal (SIGALRM, fxn) == SIG_ERR)
    perror ("Setting your function as timer handler failed");
unsigned seconds = 42;//your time
struct itimerval old, new_time;
new_time.it_interval.tv_usec = 0;
new_time.it_interval.tv_sec = 0;
new_time.it_value.tv_usec = 0;
new_time.it_value.tv_sec = (long int) seconds;
if (setitimer (ITIMER_REAL, &new_time, &old) != 0)
    perror ("Setting the timer failed");

或在窗口中:

#include <Windows.h>

void Fxn_Timer_Proc_Wrapper(HWND,UINT,UINT_PTR,DWORD){
    fxn();
}

unsigned seconds = 42;//your time
UINT_PTR timer_id;
if ( (timer_id = SetTimer(NULL,NULL,seconds *1000,(TIMERPROC) Fxn_Timer_Proc_Wrapper) == NULL){
    //failed to create a timer
}

【讨论】:

  • @MikeB 没什么,仅供参考,您也可以将&amp;old 替换为NULL 就可以了。
【解决方案2】:

这可能不是您正在寻找的,但我觉得应该澄清一下: sleep 调用只挂起调用线程,而不是进程的所有线程。因此,您仍然可以在其中一个休眠时运行并行线程。 有关更多信息,请参阅此问题: Do sleep functions sleep all threads or just the one who call it?

要解决您的问题,您应该使用定时器中断注册您的函数。请参阅其他答案以了解如何做到这一点。

【讨论】:

    【解决方案3】:

    10ms 处于可实现的边缘,请参阅stack overflow : 1ms timer 。但是,确实提出了一些关于如何获得 10ms 的建议。

    1. timerfd_create 允许您的程序使用 select 等待。
    2. timer_settime 允许您的程序请求 10 毫秒的间隔。

    Linux 的注意事项是:-

    1. 可能没有安排 - 操作系统可能正忙于做其他事情。
    2. 可能不准确 - 因为 10 毫秒似乎是有效的最短时间间隔,它可能是 +/- 1 或 2 毫秒。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-24
      • 2022-11-30
      • 2011-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多