不使用C语言中的semapore进行数据同步

我需要在我的代码中进行数据同步。 目前我正在访问中断内部的全局值以及本地函数,如果中断调用频繁,可能会破坏数据。 我需要避免这种情况。 我没有在我的代码中使用操作系统,所以我不能使用信号量。 使用类似于信号量的锁定方法可能会解决我的问题。

任何帮助,将不胜感激

中断与线程或进程的工作方式不同 – 如果线程等待信号量,则只有在信号量可用或者给定等待超时时才会调度。 同时,可以安排其他线程,其中一个可能回馈信号量。

中断服务程序不是这种情况 – 这些程序不会被任何线程调度(如果有的话,只有其他中断)中断,而是在它们返回之前执行。 因此,如果ISR等待信号量(或者类似的机制,就像你要求的那样),我们就陷入了僵局,因为持有它的线程不能再被安排给信号量了…

所以你需要一个完全不同的机制!

通常的方法是,只要您的函数需要访问公共数据,并在之后重新启用它,就会禁用中断(并且您可能也需要在ISR本身内执行此操作)。

怎么样? 那么,OS /硬件特定 – 只要你不提供进一步的细节,我就在这里……

只是一些提示:保持禁用中断的时间尽可能短,并确保常用的数据被声明为volatile!

它可能在您的主代码中就像这样简单:

disable_interrupts(); value += 1; enable_interrupts(); 

因此,在使用主代码中的值时,请确保不会触发中断。

您需要的是对数据的primefaces访问。 如果它是单个变量并且您可以保证访问是primefaces的,那就足够了。 但是,这涉及反汇编C代码,看看你最终得到了什么。 即使机器代码最终成为primefaces(单指令),它也不会是可移植的。

如果你有一个支持C11的现代编译器,你可以将共享变量声明为_Atomic ,这将解决问题。

另一种方法是在调用者的可变访问期间简单地关闭特定的中断。 但这会破坏实时性能,您可能会错过中断。

普遍的“最佳”解决方案可能是自己发明一个信号量。 例:

 // volatile to prevent dangerous compiler optimizations; does not solve re-entrancy volatile uint32_t data; volatile bool guard; void ISR (void) { if(!guard) { data = SOME_REGISTER; } } void main (void) { ... guard = true; uint32_t local = data; guard = false; } 

在上面的例子中,根本没有保证primefaces访问,甚至guard变量都没有。 但是,不再需要它,因为在main()即将读取数据时,保证设置保护。 如果在读取期间中断将启动,则不会破坏数据。

此解决方案的唯一缺点是,在设置防护时,您将错过更新data 。 如果这是一个问题,您将必须实现某种方式的临时存储。

(请注意,此代码不会导致“内存障碍”,因此在复杂的多核处理器上,此方法可能无法正常工作,而且volatile不一定会导致内存障碍。在普通微控制器上,它可以正常工作。)