睡觉一段确切的时间

我对睡眠function的理解是它遵循“至少语义”,即睡眠(5)将保证线程hibernate5秒,但是根据其他因素,它可能会保持阻塞超过5秒。 有没有办法在指定的时间段内睡觉(没有忙碌的等待)。

正如其他人所说,你真的需要使用实时操作系统来尝试实现这一目标。 精确的软件定时非常棘手。

然而……虽然不完美,但通过简单地提高需要更好时间的过程的优先级您可以获得比“正常”更好的结果 。 在Windows中,您可以使用SetPriorityClass函数实现此SetPriorityClass 。 如果将优先级设置为最高级别( REALTIME_PRIORITY_CLASS: 0x00000100 ),您将获得更好的计时结果。 再一次 – 这不会像你要求的那样完美。

这也可能在Windows以外的其他平台上实现,但我从来没有理由这样做,所以没有测试过。

编辑:根据Andy T的评论,如果您的应用程序是multithreading的,您还需要注意分配给线程的优先级。 对于Windows,这里记录了这一点。


一些背景……

SetPriorityClass我使用SetPriorityClass来提升应用程序的优先级,我正在对高速video进行实时分析,我不能错过任何一帧。 帧以非常规的(由外部帧抓取器硬件驱动)频率以每秒300帧(fps)的速度到达计算机,这会在我接下来服务的每一帧上发出一个HW中断。 由于时间非常重要,我收集了很多关于中断时序的统计信息(使用QueryPerformanceCounter东西),看看情况真的有多糟糕,并对结果发行版感到震惊。 我没有方便的统计数据,但基本上Windows正在服务中断,只要它在正常优先级运行时感觉它。 直方图非常混乱,stdev比我的~3ms周期宽。 在中断服务中经常会有200 ms或更大的巨大间隙(回想一下,中断大约每3 ms发出一次)! 即:HW中断是精确的FAR! 你坚持操作系统决定为你做的事情。

但是 – 当我发现REALTIME_PRIORITY_CLASS设置并使用该优先级进行基准测试时,它显着更好,并且服务间隔分布非常紧张。 我可以运行10分钟300 fps并且不会错过任何一帧。 测量的中断服务周期几乎完全是1/300秒,分布紧凑。

此外 – 尝试并尽量减少操作系统正在做的其他事情,以帮助提高您的时间安排在应用程序中更好地工作的几率。 例如:当你试图用其他代码获得精确计时时,没有背景video转码或磁盘去碎片或任何东西!!

综上所述:

  1. 如果您真的需要这个,请使用实时操作系统
  2. 如果您无法使用实时操作系统(不可能或不切实际),提高您的流程优先级可能会大大改善您的时间安排,就像它对我的操作一样
  3. 硬件中断不会这样做……操作系统仍然需要决定为它们提供服务!
  4. 确保您没有运行许多其他正在竞争操作系统注意的进程
  5. 如果时间对您来说非常重要,请进行一些测试。 尽管让代码在您想要的时间运行时并不容易,但测量这种偏差非常容易。 PC中的高性能计数器(使用QueryPerformanceCounter得到的)非常好。

因为它可能会有所帮助(虽然有点偏离主题),这是我很久以前在Windows机器上使用高性能计数器写的一个小类。 它可能对您的测试有用:

CHiResTimer.h

 #pragma once #include "stdafx.h" #include  class CHiResTimer { private: LARGE_INTEGER frequency; LARGE_INTEGER startCounts; double ConvertCountsToSeconds(LONGLONG Counts); public: CHiResTimer(); // constructor void ResetTimer(void); double GetElapsedTime_s(void); }; 

CHiResTimer.cpp

 #include "stdafx.h" #include "CHiResTimer.h" double CHiResTimer::ConvertCountsToSeconds(LONGLONG Counts) { return ((double)Counts / (double)frequency.QuadPart) ; } CHiResTimer::CHiResTimer() { QueryPerformanceFrequency(&frequency); QueryPerformanceCounter(&startCounts); // starts the timer right away } void CHiResTimer::ResetTimer() { QueryPerformanceCounter(&startCounts); // reset the reference counter } double CHiResTimer::GetElapsedTime_s() { LARGE_INTEGER countsNow; QueryPerformanceCounter(&countsNow); return ConvertCountsToSeconds(countsNow.QuadPart - startCounts.QuadPart); } 

没有。

它至少是“语义”的原因是因为在那5秒之后,其他一些线程可能会忙。

每个线程都从操作系统获取时间片。 操作系统控制线程的运行顺序。

当您将线程置于hibernate状态时,操作系统会将该线程置于等待列表中,当计时器结束时,操作系统会“唤醒”该线程。
这意味着线程被添加回活动线程列表,但不保证首先添加t。 (如果需要在特定的第二个线程中唤醒100个线程怎么办?谁先走?)

虽然标准Linux不是实时操作系统,但内核开发人员密切关注在保持内核锁定时高优先级进程将保持饥饿的时间。 因此,库存Linux内核通常足以满足许多软实时应用程序的需求。

您可以使用SCHED_FIFOSCHED_RR通过sched_setscheduler(2)调用将进程安排为实时任务。 两者在语义上略有不同,但可能足以知道SCHED_RR任务最终会由于时间片而将处理器放弃到具有相同优先级的另一个任务,而SCHED_FIFO任务只会将CPU放弃到另一个任务。由于阻塞I / O或对sched_yield(2)的显式调用导致相同的优先级。

使用实时计划任务时要小心; 因为它们始终优先于标准任务,所以您可以轻松地找到自己编码的无限循环,从而不会放弃CPU并阻止管理员使用ssh来终止进程。 因此,以更高的实时优先级运行sshd可能没什么坏处,至少在您确定已经修复了最严重的错误之前。

有一些可用的Linux可用于提供硬实时保证。 RTLinux有商业支持 ; Xenomai和RTAI是针对Linux的实时扩展的竞争实现,但我对它们一无所知。

正如之前的回答者所说:没有办法确切(一些建议的实时操作系统或硬件中断,甚至那些都不准确 )。 我认为你所寻找的东西比sleep()函数更精确,你会发现这取决于你的操作系统,例如Windows Sleep()函数或GNU下的nanosleep()函数。

http://msdn.microsoft.com/en-us/library/ms686298%28VS.85%29.aspx

http://www.delorie.com/gnu/docs/glibc/libc_445.html

两者都会在几毫秒内为您提供精确度。

那么,你试图解决一个棘手的问题,并且实现精确的时间是不可行的: 你能做的最好就是使用硬件中断 ,实现将取决于底层硬件和操作系统(即,你需要一个实时操作系统 ,大多数常规桌面操作系统都没有)。 您的确切目标平台是什么?

不会。因为您总是依赖操作系统来处理在正确的时间唤醒线程。

使用标准C无法在指定的时间段内hibernate。您至少需要一个提供更大粒度的第三方库,您可能还需要一个特殊的操作系统内核,例如实时Linux内核。

例如,下面讨论一下Win32系统的接近程度 。

这不是C问题。