2013-04-03 23 views
1

我正在開發一個相當複雜的微控制器應用程序C,我對如何將不同任務/線程之間的共享數據「鏈接」而不耦合它們存在一些疑問。如何在任務/線程之間共享數據而不耦合它們?

到現在爲止,我已經使用了時間片調度程序來運行我的應用程序,因此不需要數據保護。但是我想讓應用程序正確,我想在稍後爲多線程操作系統做好準備。

我試圖通過使用完全不同的系統,而不是我正在工作的實際系統來簡化我的問題。我無法添加圖片,因爲我是新用戶,但生病嘗試並解釋:

我們得到4個任務/線程:3個輸入線程,通過硬件抽象層(HAL)從不同傳感器讀取一些傳感器數據。 。收集的傳感器數據存儲在任務域(即:他們不會是全球性的!)。 現在我們還有1個輸出任務,我們稱之爲「調節器」。調節器必須使用(讀取)從所有3個傳感器收集的傳感器數據才能生成正確的輸出。

問題:Regulator如何讀取存儲在不同輸入任務中的採集數據而不與其他任務耦合?

調節器只能通過參考知道輸入任務及其數據(即:不包含,不耦合)。

到目前爲止,Regulator已經有了一個指向每個所需傳感器數據的指針,並且該指針在初始化時設置。由於數據保護,這不會在多線程應用程序中工作。

我可以做一些getSensorValue()功能,它利用信號量,爲每個傳感器值,然後用函數指針將這些函數鏈接到調節器。但是這會佔用很多內存!有沒有更好的方法來做到這一點?我只是在尋找投入。

我希望這一切都是可以理解的:)

+0

你在運行什麼硬件?微控制器系列對可以完成的工作產生很大的影響。例如在許多微控制器上沒有虛擬內存。在其他控制器的「線程」中實際上並不是線程,而只是看門狗交換的堆棧指針。 – Pyrce

+0

目前我在PSoC5上運行,我計劃進行端口/轉換爲STM32? – Jolle

+0

這些家族看起來有真正的線程/虛擬內存表。當你說數據保護會阻止應用程序讀取線程特定的數據時,你的意思是說這些'線程'是作爲進程而不是線程啓動的嗎?因爲線程可以讀取其他線程的內存,除非你用'__thread'等線程本地關鍵字來顯式地限制內存。你認爲什麼內存很多,3個信號燈應該只佔用幾個字節的內存。或者由於傳感器的讀取速度,線程不能被延長時間阻塞? – Pyrce

回答

2

從您的問題描述了和評論,好像你最擔心內存不足的以最小的實施細則,並沒有傳感器和監管者之間的接口是瞭解每個傳感器實現的明確細節。

由於您在C中,並且沒有一些C++類的特性可以通過繼承來簡化封裝,所以我建議您從每個傳遞給調節器的傳感器線程創建一個通用數據包,而不是傳遞一個函數指針。形式

struct SensorDataWrap { 
    DataType *data; 
    LockType *lock; 
    ... other attributes such as newData or sensorName ... 
}; 

的結構將允許您將數據傳遞到監管機構,在那裏你可以閱讀前鎖定。同樣,傳感器在寫入之前需要鎖定。如果您將數據更改爲雙指針DataType **data,則可以使寫命令只需鎖定交換基礎指針所需的時間。然後,調節器只需要每個線程的一個SensorDataWrap結構來處理該線程的信息,而不管傳感器實現細節如何。

LockType可能是一個信號量,或者任何能夠實現單一訪問獲取的更高級鎖定對象。任何此類鎖的內存佔用空間應僅爲幾個字節。此外,您並不是在這裏複製數據,因此相對於傳感器讀數,您不應該對內存大小產生任何乘法影響。您使用的硬件應具有足夠的空間來容納來自所描述的傳感器的單個數據副本以及足夠的閃存空間以容納信號量或鎖定對象。

通信的實現細節現在僅限於鎖定,操作,解鎖,不需要複雜的函數指針或SensorN特定的頭文件包含。它應該接近任何線程共享數據程序所需的最小邏輯。該程序也應該可以轉移到其他微控制器而沒有重大改變 - 通信僅僅受到線程和鎖定的存在/限制的限制。

另一種選擇是傳遞三重緩衝區對象並做緩衝區翻轉以避免信號量和鎖定。這種方法需要創建原子整數/布爾支持(如果您有信號量,最有可能已由編譯器公開)。可以在this blog上找到使用三重緩衝區並行的指南。這種方法將使用更多的活動內存,但它是避免大多數併發問題的一種非常流暢的方式。

+0

好的!這聽起來(有點像)消息隊列,我有這個想法,但結論(實際上沒有任何好的論據),這是一個矯枉過正。雖然這不完全是你說的對嗎?如果我明白這個權利,Regulator應該有一個SensorDataWrap的實例(應該爲傳感器和調節器btw聲明typedef),並且SensorDataWrap裏面有兩個數據和某種保護機制。我喜歡這個主意!雖然我不太瞭解雙指針部分。 – Jolle

+0

的確,我寫出來的實現是一個簡化的消息隊列,監管者負責在數據被傳感器覆蓋之前讀取數據。一個消息隊列的實現也會起作用,而且不會矯枉過正。雙指針是一個小調。單個指針版本要求傳感器在將所有讀數寫入數據的同時保持鎖定。一個雙指針可以讓他們寫入一個新的「數據」對象,並且只有在他們改變指針以解決新讀取時才鎖定。這需要內存管理,所以它不是明顯更好。 – Pyrce

+0

好吧,我認爲這比消息隊列更好,因爲調節器是實時的,因此它不一定會像傳感器產生的那樣快地消耗數據。監管機構應該隨時訪問最新的數據。但非常感謝你,那只是我正在尋找的那種輸入! – Jolle