簡體   English   中英

在不使用C的情況下進行數據同步

[英]data synchronization without using semapore in C

我需要在代碼中進行數據同步。 目前,我正在中斷內部以及局部函數中訪問全局值,如果頻繁調用中斷,則該局部值可能會破壞數據。 我需要避免這種情況。 我的代碼中未使用操作系統,因此無法使用信號燈。 使用與信號量類似的鎖定方法可以解決我的問題。

任何幫助,將不勝感激

中斷的工作方式不同於線程或進程-如果線程等待信號量,則直到信號量可用或等待超時(如果給定)過去時,線程才進行調度。 同時,可以調度其他線程,其中一個線程可能會發回信號量。

中斷服務例程不是這種情況-這些不會被任何線程調度中斷(如果有的話,只會被其他中斷中斷),但是會執行直到返回。 因此,如果ISR等待信號量(或您所要求的類似機制),我們將陷入僵局,因為持有該信號的線程無法再被調度以返回信號量了。

因此,您需要一種完全不同的機制!

執行此操作的通常方法是,只要您的函數需要訪問公用數據,就禁用該中斷,然后再重新啟用它(並且您可能也需要在ISR本身中執行此操作)。

怎么樣? 好吧,特定於操作系統/硬件-只要您不提供更多詳細信息,我就在這里...

僅有一些提示:保持禁用中斷的時間盡可能短,並確保將通常訪問的數據聲明為易失性!

在您的主代碼中可能就這么簡單:

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

因此,請確保在使用主代碼中的值時不會觸發中斷。

您需要的是對數據的原子訪問。 如果它是單個變量,並且您可以保證訪問是原子的,那么這就足夠了。 但是,這涉及到反匯編C代碼並查看最終結果。 即使機器代碼最終以原子(單指令)的形式出現,它也不是可移植的。

如果您具有支持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;
}

在上面的示例中,根本無法保證原子訪問,甚至不能保證可以訪問guard變量。 但是,這不再是必需的,因為在main()將要讀取數據的那一點上,可以保證設置了guard 如果在讀取期間插入中斷,則不會破壞數據。

該解決方案的唯一缺點是,設置了防護后,您將丟失更新data的機會。 如果這是一個問題,則您將必須實施某種方式的臨時存儲。

(請注意,此代碼不會導致“內存障礙”,因此在復雜的多核處理器上,此方法可能不起作用,並且volatile不一定會導致內存障礙。但是在普通微控制器上,它會很好地工作。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM