2

我正在做一个项目,当某个线程开始执行时,我需要阻塞所有线程。我考虑过使用线程标志,但我相信这将涉及向所有线程添加检查。我还考虑过使用互斥锁来阻止除我需要执行的关键线程之外的所有线程/拥有对处理器的唯一控制权。我还没有使用互斥锁的原因是因为我已经读过它只与资源有关,并且如果它们没有链接到互斥锁,某些线程仍然会继续执行,但是我可能误解了这一点。

您能否告诉我我对互斥体想法的方法是否正确,或者我是否应该使用另一种方法?

编辑:我在 STM32H753 芯片上使用 Keil RTX 5/CMSIS RTOS 2

谢谢

4

3 回答 3

3

CMSIS RTOS 具有一对功能osKernelLock(),并且osKernelUnlock()- 动态修改线程优先级或使用互斥锁是不必要的,并且可能是不明智的。

任何其他 RTOS 都将具有类似的临界区API。

请注意,这只会阻止任务上下文切换;它不会阻止中断运行。这通常是可取的,但如果您想防止这种情况,您可以简单地使用_disable_irq()/_enable_irq()禁用所有中断。这将防止任务切换中断。

禁用中断是蛮力的,并且对系统的实时行为有更大的影响,甚至是调度程序锁定。通常它应该只在很短的时间内完成(调度程序锁定也应该如此)。

于 2020-01-13T18:54:46.547 回答
0

你用的是什么实时操作系统?我假设您使用的是基于优先级的 RTOS。

不要将另一个调度机制与线程标志或互斥体分层。只需使用您已有的调度程序。

如果您希望一个线程独占运行,则将该线程设为最高优先级线程。RTOS 调度程序将运行准备好运行的最高优先级线程。如果您的线程具有最高优先级并且不阻塞自身,则其他线程将不会运行。在 CMSIS-RTOS 中,您可以使用osThreadSetPriority().

于 2020-01-06T13:53:38.820 回答
0

不要直接从用户代码更改任务的优先级。大多数 RTOS 提供了使我们能够做到这一点的 API,但这是一种糟糕的风格,因为它产生的问题比它所能解决的要多。一个例外是当某些 RTOS 在内部对此起作用时(例如,具有优先级继承的互斥锁以避免某些多任务问题)。

我猜您只想在系统的启动阶段或运行时的另一个非常特殊的阶段拥有更长的关键部分。否则,您应该真正听取@Clifford 的评论并质疑您的优先分配和任务分解

如果您仅在初始化/上电阶段需要该连续周期,这也是一种典型的情况,也可以通过良好的任务设计来实现。在这种情况下,您需要的是运行级别管理

运行级别管理

实现这一点的最简单方法是在 RTOS 之上编写一个小库,使用两个计数信号量资源:一个用于当前运行级别,另一个用于下一个运行级别。当输入运行级别时,信号量将填充与必须在运行级别管理控制下的任务一样多的标记。每个等待处理给定运行级别的任务都试图从当前运行级别的信号量中获取其令牌。当任务完成其运行级别部分时,它会访问下一级信号量,此时该信号量将不可用。

在填充运行级别管理配置之前,您可以自己绘制一个 序列图 来检查在哪些点上,任务必须等待其他任何原因。通常对于每个任务,只有少数运行级别是相关的 - 每个运行级别,相关任务的集合也可能很小。因此,您可能想要添加一个小辅助函数,例如WaitForRunlevelNumber(N)自动处理那些不相关的运行级别的循环。

如果需要显式同步的所有阶段都已完成,则必须完成运行级别管理。然后,所有任务都被释放到自由中。有时,如果低优先级任务已完成所有关键阶段,您希望提前释放它们。然后,维护的任务数量可能会从一个运行级别减少到下一个运行级别。

于 2020-05-01T17:04:57.753 回答