在多线程上下文中实施实时约束

时间:2013-05-28 15:15:32

标签: c++ multithreading real-time

我目前正在开发一个用C ++编写的GUI,用于一个必须实时轮询,处理然后显示数据(带图)的程序。

我正在努力解决的部分是代码,它运行在一个单独的线程中,实际上是从一些外部硬件轮询数据然后处理它。我希望以固定的周期(即调用之间的1/20秒)定期调用执行此工作的函数。

我真的不知道是否可能以及如何强制执行必须定期调用该函数的事实,每秒正好调用20次......

在阅读了一些关于实时编程的内容之后,基于我从游戏开发和主游戏循环的概念中学到的东西,我的第一种方法是使用一个循环,根据如何调整执行时间轮询+处理花了很多时间:

 while(running){
     //Let's assume this function get the time elapsed since
     //the program started
     int start = get_current_time_millisecond();

     //Retrieve the data from the hardware
     pollData();

     //Process the data retrieved
     processData();

     //Queue the data wherever it is needed:
     //- plotting widget of the GUI
     //- recording object
     dispatchProcessedData();

     int elapsed = get_current_time_millisecond() - start;
     int remaining = 50 - elapsed;

     if(remaining > 0){
         sleep(remaining);
     }
 }

但这似乎有缺陷,因为如果在一次迭代中经过的时间大于我想要坚持的时间,它可能会导致漂移问题。

这可能来自于计算花费太多时间的事实(我非常怀疑它,但我没有足够的经验来确定,并且分析可以帮助消除这个问题,或者至少确定代码可能花了很多时间),但我也想知道我运行多线程的事实是否会因为线程调度而导致同样的问题(再次,我对多线程很新,我可能完全错了)。

因此,我想问:

  • 是否可以通过实时编程强制执行此类约束(在多线程上下文中,如果相关)以及如何实现?
  • 在设计此类代码时,我应遵循哪些主要指南?

(如果我错过了很明显/很容易找到关于这个主题的文档,我道歉)

谢谢!

2 个答案:

答案 0 :(得分:3)

除非你有一个外部可靠的中断来源,否则很难强制执行这样的约束。

我相信你在消费者操作系统上最接近的事情是:

  • 确保您使用实时内核(例如,使用Linux的RT补丁)以最小化时序变化。
  • 将轮询线程设置为最高优先级。
  • 仅在轮询线程中进行轮询和分派,将任何处理留给优先级较低的线程,以便计算不会影响您的轮询。
  • 使用高精度计时器(在Linux上可以有纳秒而不是毫秒)来减少误差范围。
  • 使用无锁队列在轮询和处理线程之间进行通信,这样您就不必在轮询线程中支付互斥锁的成本(但每秒只有20个样本,这可能无关紧要)。 / LI>

至少这是我们为我们的产品所做的,它在400 MHz CPU上以100Hz(10ms)进行轮询。你永远不会完全摆脱这种漂移,但它是非常小的。

答案 1 :(得分:1)

正如@Mark建议的那样,最好的方法是使用实​​时操作系统。

如果某种“软”RT很好,你应该创建一个具有高优先级的线程(例如在Linux中使用调度类实时FIFO或类似的东西)并设置一个循环计时器,它会唤醒你的线程,例如通过信号量。

此外,将绘图与处理分离是个好主意。