【问题标题】:Implementing time delay function in C在 C 中实现时间延迟功能
【发布时间】:2015-07-21 19:55:49
【问题描述】:

我想使用空循环实现延迟功能。但是完成一次循环所需的时间取决于编译器和机器。我希望我的程序自行确定时间并将程序延迟指定的时间。谁能给我任何想法如何做到这一点? N. B. 有一个名为 delay() 的函数将系统挂起指定的毫秒数。不使用这个功能是否可以挂起系统?

【问题讨论】:

  • delay() 函数取决于操作系统和机器。它不是 C 语言的什么神奇功能,它只是 ANSI 或 POSIX 采用的标准接口。它必须在特定硬件的内核级别上实现,这意味着它也是(编译器/机器相关的)。
  • 如果您不是在内核级别的编程,即 unix、windows 等中的用户应用程序,为什么要重新发明轮子?如果您处于内核级别,则必须了解硬件如何使用带有计时器的寄存器等。
  • 从 C11 开始,该标准现在提出了一个独立于操作系统的接口thrd_sleep。不幸的是,并非所有编译器都实现了这一点,但即将到来。
  • Linux 中的 usleep()/nanosleep() 或 Windows 中的 Sleep() 肯定会起作用,但我的经验是,任何时候你认为你想要在程序中出现这样的延迟,这是因为你没有考虑到你真正需要的东西。你到底想完成什么?

标签: c delay


【解决方案1】:

首先,您应该永远不要无所事事地坐在循环中。它不仅浪费能源(因为它让你的 CPU 100% 忙于计算你的循环计数器)——在多任务系统中,它还会降低整个系统的性能,因为你的进程一直在获得 时间片 看起来正在做某事的时间。

下一点是......我不知道任何delay() 函数。这不是标准 C。事实上,在 C11 之前,根本就没有这样的标准。

POSIX 来拯救,有usleep(3)(已弃用)和nanosleep(2)。如果您使用的是符合 POSIX 的系统,那么您可以使用这些系统。它们阻塞(意味着您的操作系统的调度程序知道它们无事可做,并且仅在调用结束后调度它们),因此您不会浪费 CPU 功率。

如果您在 Windows 上,对于代码的直接延迟,您只有 Sleep()。请注意,这个函数需要几毫秒,但通常只有大约 15 毫秒的精度。通常足够好,但并非总是如此。如果您需要在 Windows 上获得更高的精度,您可以使用 timeBeginPeriod() 请求更多定时器中断 ...timeBeginPeriod(1); 将每毫秒请求一个定时器中断。当您不再需要精度时,不要忘记使用 相同的值 调用 timeEndPeriod(),因为更多的定时器中断是有代价的:它们使系统保持忙碌,从而浪费更多能量。

我最近在开发一个小游戏时遇到了类似的问题,我需要以 10 毫秒的间隔持续滴答,这就是我想出的 for POSIX-compliant systemsfor windows。这段代码中的 ticker_wait() 函数只是暂停到下一个滴答声,如果您最初的意图是一些时间问题,这可能会有所帮助。

【讨论】:

    【解决方案2】:

    除非您使用的是实时操作系统,否则您直接自己编程的任何内容都不会准确。您需要使用系统函数来休眠一段时间,例如 Linux 中的 usleep 或 Windows 中的 Sleep

    由于操作系统可能早于或晚于预期的确切时间中断进程,因此您应该获取睡眠前后的系统时间以确定您实际睡眠了多长时间。

    编辑:

    在 Linux 上,您可以使用 gettimeofday 获取当前系统时间,其分辨率为微秒(实际时钟是否准确则另当别论)。在 Windows 上,您可以使用 GetSystemTimeAsFileTime 执行类似的操作:

    int gettimeofday(struct timeval *tv, struct timezone *tz)
    {
        const unsigned __int64 epoch_diff = 11644473600000000;
        unsigned __int64 tmp;
        FILETIME t;
    
        if (tv) {
            GetSystemTimeAsFileTime(&t);
    
            tmp = 0;
            tmp |= t.dwHighDateTime;
            tmp <<= 32;
            tmp |= t.dwLowDateTime;
    
            tmp /= 10;
            tmp -= epoch_diff;
            tv->tv_sec = (long)(tmp / 1000000);
            tv->tv_usec = (long)(tmp % 1000000);
        }
    
        return 0;
    }
    

    【讨论】:

    • 您是否正在考虑使用 time() 函数来获取系统时间?
    • gettimeofday(2) 自 SUS v4 起已过时;你应该推荐clock_gettime(2)
    • 另外:使用系统函数睡眠不一定比滚动你自己的函数更准确。正如您所说,Linux 不是一个实时操作系统,因此无论如何都会发生延迟。
    【解决方案3】:

    您可以执行一些操作,例如找到某个时间点的确切时间,然后将其保存在一个 while 循环中,该循环会重新检查时间,直到它到达您想要的任何时间。然后它就会爆发并继续执行程序的其余部分。我不确定我是否在循环中看到了很多好处,而不仅仅是使用延迟函数。

    【讨论】:

      猜你喜欢
      • 2019-01-03
      • 2011-10-29
      • 1970-01-01
      • 1970-01-01
      • 2012-06-02
      • 1970-01-01
      • 2021-03-24
      • 1970-01-01
      • 2011-05-02
      相关资源
      最近更新 更多