【发布时间】:2020-12-16 09:45:39
【问题描述】:
在 vxWorks 6.9 中,您可以创建计时器,它们实际上只是看门狗的包装。您为这些人提供一个函数指针、一个延迟和最多一个参数,然后在延迟之后使用该参数调用该函数。但是,它是在中断上下文中调用的。这(出于某种原因)意味着您不能调用任何“阻塞”函数,否则系统会崩溃。你不能调用printf,也不能调用对象的公共函数,也就是说你不能这样做:
void Foo::WdCallback(Foo *foo){
foo->DoThing();
}
wdStart(wd, 16, (FUNCPTR)Foo::WdCallback, (_Vx_usr_arg_t)my_foo_ptr);
因为我不明白的原因它也会崩溃。
还有什么其他方法可以在 vxWorks 中创建计时器/超时,以便我们可以对回调实际做一些有用的事情?我见过的一种方法是使用消息队列——看门狗函数将调用消息队列发送函数。然而,这意味着必须创建一个任务来将该消息队列出列到其他地方。我还读到看门狗回调可以提供一个信号量,允许任务继续,但这意味着我们必须为我们想要的每个基于计时器的函数创建一个任务..
看起来无论我们在 vxWorks 中使用看门狗或计时器采取何种方式,我们都必须创建一个完整的任务,以便能够处理由于中断上下文而引起的看门狗回调。必须有一种不那么荒谬的方法来做到这一点。是否有纯粹的 C++ 方法来编写计时器?还是更简单的 vxWorks 实现?
【问题讨论】:
-
成员函数有一个
this的隐式参数,但该参数在排序中的位置取决于 AFAIK 的实现。 -
'这意味着我们必须为我们想要的每一个基于计时器的函数创建一个任务',不,你不需要。您只需要一个任务来维护按超时时间排序的超时结构列表。此任务将中断计时器设置为在距列表头部最近的超时后触发。结构可以有函数指针,或者派生自具有实际超时方法的“超时”类的实例。
-
'但是如果超时线程可以随时抢占并删除它刚刚超时的列表头部的项目,我如何安全地添加/删除/列表中的任何项目' - 你通过将超时实例推送到线程安全的“命令”队列并发出信号量来请求超时任务来完成这些工作。当超时任务运行时,它现在做两件事:检查命令队列中是否有任何新的超时请求,并检查超时列表头以查看它是否已经超时。如果是,则处理,如果不是,重新计算剩余时间,设置中断定时器,等待信号量。