Windows操作系统中(软实时)时序要求的限制

时间:2014-07-19 14:23:42

标签: c# windows multithreading real-time

在我工作的公司中,我们构建的机器由运行在Windows操作系统上的软件控制。 C#应用程序与总线控制器通信(通过DLL)。总线控制器的运行时间为15ms。这意味着,我们可以从总线控制器获得系统中实际传感器的更新,其心跳距离为15ms( 实时)。

现在,这些机器正在发展成为下一代,我们得到一个新的总线控制器,运行时间为1毫秒。由于每个人都意识到Windows不是实时操作系统,所以问题就出现了:我们应该将软件的控制部分移动到实时应用程序(在实时操作系统上,例如(软)PLC)。

如果我们留在Windows平台上,我们没有保证响应能力。这本身不一定是个问题;如果我们错过了几个总线周期(有一些hickup),机器只会产生稍慢的速度(这是可以接受的)。

让我担心的部分是主机控制线程之间的线程同步,以及我们从实时控制器(每毫秒)收到的更新。

在哪里可以了解更多有关Windows / .NET C#在毫秒级下线程同步路径时的行为?我知道,例如Thread.Sleep(1)可能需要15毫秒,因为Windows正在抢占其他任务,那么当我每隔ms Monitor.PulseAll同步两个线程时,这是如何反映出来的?我可以期待同样不可预测的行为吗?当我在Windows应用程序中进入1ms的软实时要求时,是否会遇到麻烦?

我希望在线程的这些方面有经验的人可以对此有所了解。如果我需要澄清更多,一定要拍摄。

2 个答案:

答案 0 :(得分:1)

您的方案听起来像是信息亭模式/专用应用程序的候选者。

  

在我工作的公司中,我们构建的机器由运行在Windows操作系统上的软件控制。

如果是这样,您可以对机器进行装配,以便您的低延迟I / O线程可以在专用内核上运行,并且线程和进程优先级最大化。此外,确保机器具有足够的内核来处理缓冲线程以及处理传输中数据的任何其他线程。如果可能,缓冲区应该预先分配内存,以避免垃圾收集瓶颈。

@ Aron的例子适用于数据完整性可能在某种程度上受到损害的情况。在音频中,由于多种原因,在录制期间延迟很重要,但对于纯播放,数据丢失在某种程度上是可接受的。我假设这不是你的选择。

当然,Windows并非设计为实时操作系统,但如果您将其用于专用应用程序,则可以控制它的各个方面,并可以关闭所有不相关的服务和后台进程。

我已经在编写软件方面取得了相当大的成功,通过测量其功率补偿响应时间来监控UPS单元应对功率波动的程度(免责声明:不是出于商业目的)。由于每个样本测量的数据非常小,因此GC没有问题,我们为缓冲区循环预先分配的内存块。

一些微观优化派上用场:

  • 使用不可变structs轮询I / O数据。
  • 优化数据结构以便与内存分配配合良好。
  • 优化处理算法以最大限度地减少CPU缓存未命中。
  • 使用优化的缓冲区类来保存传输中的数据。
  • 使用MonitorInterlocked类进行同步。
  • 使用(void*)的不安全代码以各种方式轻松访问缓冲区阵列,以减少处理时间。最少使用MarshalBuffer.BlockCopy

最后,您可以使用DDK方式编写一个小驱动程序。虽然偏离主题,但DFMirage是视频驱动程序的一个很好的示例,它为差异屏幕捕获提供基于事件和轮询的模型,以便消费者应用程序可以根据系统负载即时选择。

对于Thread.Sleep,考虑到您的能耗边界,您可以尽可能少地使用它。通过冗余进程,Thread.Sleep(1)不应该像你想象的那么糟糕。尝试以下方法,看看你得到了什么。请注意,这已在SO编辑器中编码,因此我可能犯了错误。

Thread.CurrentThread.Priority = ThreadPriority.Highest;
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime;

var ticks = 0L;
var iteration = 0D;
var timer = new Stopwatch();

do
{
    iteration++;
    timer.Restart();
    Thread.Sleep(1);
    timer.Stop();
    ticks += timer.Elapsed.Ticks;

    if (Console.KeyAvailable) { if (Console.ReadKey(true).Key == ConsoleKey.Escape) { break; } }

    Console.WriteLine("Elapsed (ms): Last Iteration = {0:N2}, Average = {1:N2}.", timer.Elapsed.TotalMilliseconds, TimeSpan.FromTicks((long) (ticks / iteration)).TotalMilliseconds);
}
while (true);

Console.WriteLine();
Console.WriteLine();
Console.Write("Press any key to continue...");
Console.ReadKey(true);

答案 1 :(得分:0)

考虑实际问题本身,在1ms处理数据非常容易。在考虑录音时,作为一个类似的(双关语)问题,你可能会找到一些如何实现目标的灵感。

请记住。

  • 即使是适度的设置,每通道采样率也可达到44.1kHz @ 16bit(约为22微秒或不到目标的百分之一)。
  • Using ASIO you can achieve sub 10ms latencies
  • 实现高采样率的大多数方法都可以通过增加缓冲区大小并分批向系统发送数据来实现
  • 要获得最佳吞吐量,请不要使用线程。您可以通过DMA和中断来回调处理循环。

鉴于声卡通常可以实现您的目标,您可能有机会。