當前位置:首頁 > 公眾號精選 > 嵌入式云IOT技術圈
[導讀]嵌入并發(fā),意味著多線程或者多任務,基本上都是使用了系統,linux系統或RTOS系統之類的實現。

嵌入并發(fā),意味著多線程或者多任務,基本上都是使用了系統,linux系統或RTOS系統之類的實現。RTOS系統里任務的調度主要有搶占式和時間片調度兩種,具體的區(qū)別這里就不詳細說明了。此篇章包含了并發(fā)的一些術語,如并發(fā)性,臨界性,資源,死鎖等的概念。最好是詳細閱讀RTOS系統的書籍。

聲明:文章基于《C嵌入式編程設計模式》這本書,英文是Design Patterns for Embedded Systems in C。主要是做個筆記,并添加一點個人的理解,分享出來與各位探討。


1. 嵌入并發(fā)和資源管理的設計模式

總共有8個模式,前兩個循環(huán)執(zhí)行模式和靜態(tài)優(yōu)先級模式,提供了兩個不同的方法來調度任務或線程。接下來3個模式臨界區(qū)模式,守衛(wèi)調用模式和隊列模式,為了使解決在多任務環(huán)境下串行訪問資源的問題。匯合模式講的是多任務以不同的方式進行同步。最后兩個模式是關注預防死鎖問題。希望下面的模式能夠各位一點啟發(fā)。

1.1 循環(huán)執(zhí)行模式

循環(huán)模式有非常簡單的方式調用多個任務的特點,允許所有的任務有同等機會運行,但是不能及時響應緊急事件。一般在資源少的系統里面使用,避免了RTOS的開銷,也不需要復雜的任務調度。簡單就是最大的優(yōu)點。

1.1.1 模式結構

CyclicExecutive有一個controlLoop()函數,可以反復調用每個任務的run操作。也需要等待任務的結束再調用下一個任務。

1.1.2 角色

1.1.2.1 抽象任務(AbstractCEThread)

通過聲明run()函數為線程提供接口。它是用來循環(huán)執(zhí)行的任務函數。

1.1.2.2 循環(huán)控制(CyclicExecutive)

這個類用于循環(huán)執(zhí)行每個任務。此外也有全局棧和任務本身需要的靜態(tài)數據。模式的一個變體是時間觸發(fā)循環(huán)執(zhí)行,在這個變體中,CyclicExecutive設置使用CycleTimer來開啟每個周期。也就是使用這個變體可以在周期類執(zhí)行每個函數。

1.1.2.3 循環(huán)定時器(CycleTimer)

圖中有表示帶有“0,1”,這個定時器是可選的。當定時器時間到時,可以調用中斷或者返回TRUE給hasElapsed()函數。CyclicExecutive調用start()為下一個周期開始計時。

1.1.2.4 具體任務實現(ConcreteCEThread)

每個ConcreteCEThread都有自己的run()函數,用于具體的任務實現。

1.1.3 效果

如前所述,該模式優(yōu)點在于簡單,一方面很難導致調度程序錯誤,另一方面對緊急事件響應不足,使得僅使用在內存小的設備。還有缺點是,任務間的通訊會值得考慮,比如一個任務需要另一個任務的數據,那么數據只能保存在全局的內存或共享資源中。我們盡量不要定義太多的全局變量,否則會難以管理維護,和造成內存的浪費。

1.1.4 實現

該模式的實現非常簡單。在大多數情況下,循環(huán)執(zhí)行可能僅是應用的main()函數中調用。

1.2 靜態(tài)優(yōu)先級模式

大多數的實時操作系統都是靜態(tài)優(yōu)先級模式。所以想要使用這個模式直接移植RTOS系統就好了。這里的模式復雜度和完整度是無法比得上RTOS系統的,不過閱讀這里也可以使你對RTOS的任務調度有所了解,因為這是基于這個框架的。靜態(tài)優(yōu)先級模式能夠為任務劃分優(yōu)先級,能夠更好響應高優(yōu)先級時間。

1.2.1 模式結構

除了右下角AbstraceStaticThread,SharedResource,ConcreteStaticThread這三個類,其他一般是由RTOS實現。

1.2.2 角色

1.2.2.1 抽象線程(AbstraceStaticThread)

是一個抽象類,提供run()函數給調度器運行。

1.2.2.2 具體線程(ConcreteStaticThread)

ConcreteThread作為AbstraceStaticThread具體實現run()函數。

1.2.2.3 互斥鎖(Mutex)

是一個互斥的信號量類,用來串行訪問SharedResource。當一個任務調用了互斥量的lock()函數,其他任務嘗試鎖定的同一個互斥量時候,會被阻塞,直到互斥量的解鎖或超時退出。

1.2.2.4 隊列(PriorityQueue)

PriorityQueue是根據優(yōu)先級,對指向StaticTaskControlBlock的指針進行排序,也就是說隊列里存儲的其實每個線程的排隊。一般在RTOS系統里,存在不止一個隊列,有就緒隊列,阻塞隊列等,調度器會從就緒隊列取出第一個執(zhí)行。

1.2.2.5 資源(SharedResource)

該資源可能在一個或多個線程里共享,需要保證資源的正常,在下面模式會說明資源共享的問題。

1.2.2.6 棧(Stack)

每個AbstraceStaticThread都有一個棧用于返回地址和傳遞參數。

1.2.2.7 調度器(StaticPriorityScheduler)

最簡單的法則:總是運行最高優(yōu)先級的準備線程。RTOS系統里,任務創(chuàng)建,任務切換等都需要經過調度器。任務創(chuàng)建成功后,會把任務按優(yōu)先級加入到就緒列表中,任務掛起就會加入到掛起列表。系統有個滴答時鐘中斷或其他能夠進行任務切換,查找下一個運行的任務可以有通用方法,就是從就緒列表取。另一種是硬件方法,使用處理器自帶的硬件指令來實現,需要硬件本身支持。

1.2.2.8 程序控制塊(StaticTaskControlBlock)

包含了它相應的AbstraceStaticThread對象的調度信息。有線程的優(yōu)先級,默認開始地址,目前地址,只要線程還在沒被銷毀,這個塊就會伴隨著存在。

1.2.3 效果

靜態(tài)優(yōu)先級模式能夠對事件提供及時響應,可以對CPU大程序優(yōu)化,避免單線程因等待時占用CPU這種浪費。因RTOS系統的支持,線程間通訊也有很多保證,郵箱,信號量機制,避免了過多的全局變量。

1.1.4 實現

最好的方式是直接移植成熟的RTOS系統來實現。使用這種模式,需要對前期開發(fā)有個設計,對內存分配,優(yōu)先級分配等因素,需要在程序開發(fā)前有個規(guī)劃,否則可能會造成后面存在各種問題。復雜度比單線程的高,所以需要你有個深入的理解,才能對RTOS系統運用掌握,但是也不用害怕,RTOS始終還是中小的系統,有時間可以研究源碼,RTOS對指針,數據結構的運用非常的成熟高效。

1.3 臨界區(qū)模式

臨界區(qū)模式是任務協調最簡單的方式。它直接禁止了任務的切換,在臨界區(qū)內安全訪問之后,再退出臨界區(qū)。

1.3.1 模式結構

模式結構非常簡單,在進入臨界區(qū)后才訪問資源。調度程序不參與臨界區(qū)的開啟和結束過程,知識提供服務禁止和重啟任務切換。如果調度系統不提供,則臨界區(qū)能夠在硬件級別使用C的asm直接開關中斷處理。

1.3.2 角色

1.3.2.1 臨界區(qū)(CRShaaredResource)

使用這個元素來禁止任務切換,以防止任務同時訪問資源。這個例子里,受保護資源是Value屬性,相關的服務都必須使用臨界區(qū)來保護,setValue()和getValue()函數必須獨立實現臨界區(qū)。

1.3.2.2 任務集合(TaskWithSharedResource)

這個元素代表所有想要訪問共享資源的任務集。這些任務并不知道保護資源的方法,因為它被封裝在共享資源內。

1.3.3 效果

模式特點就是禁止調度任務的切換,更嚴格的,禁止所有的中斷。注意的是,一旦元素離開了臨界區(qū),將重啟任務切換,另外使用了臨界區(qū),就注定會影響到其他任務的時序,所以盡量保證臨界區(qū)的時間不要長。

1.3.4 實現

絕大多數的RTOS系統直接提供函數,調用即可。

1.4 守衛(wèi)調用模式

守衛(wèi)調用模式提供了鎖定的機制串行訪問,可以阻止當鎖定后來自其他線程的調用資源。在RTOS系統里,直白的說就是信號量。使用這個模式可能會導致優(yōu)先級導致,或死鎖的問題發(fā)生。

1.4.1 模式結構

在模式下,多個PreemptiveTasks通過他們的函數訪問GuardeResource。當一個線程調用一個正在鎖定的信號量時,調度服務會把該線程加入到阻塞隊列中,等待當那個信號量釋放或超時時,解除阻塞。調度服務必須作為臨界區(qū)實現信號量的lock()功能,以防止可能的競爭條件。

1.4.2 角色

1.4.2.1 共享資源(GuardedResource)

在這個類中使用互斥信號量來互斥訪問。在訪問資源之前,執(zhí)行與Semaphore實例關聯的lock()函數。如果Semaphore是在非鎖定狀態(tài),則變?yōu)殒i定;如果在鎖定狀態(tài),則Semaphore會調度復位發(fā)信號阻塞這個任務。

1.4.2.2 任務(PreemptiveTask)

訪問共享資源的任務。

1.4.2.3 互斥信號量(Semaphore)

它串行訪問GuardedResource。lock()函數是用于訪問資源之前,release()函數是訪問資源后,調用釋放信號量。

1.4.3 效果

該模式提供及時訪問資源,并同時阻止多個能夠導致數據損壞和系統錯誤行為的同時訪問。如果資源沒有上鎖,那么訪問資源并不會遭受到延遲。

1.4.4 實現

通過使用RTOS提供的信號量函數。一般都會提供創(chuàng)建信號量,摧毀信號量,上鎖,解鎖的接口。

1.5 隊列模式

隊列模式是任務異步通訊常見的實現。它提供了在任務間的通訊方式。發(fā)送者將消息隊列Cyrus隊列中,一段時間過后,接受者從隊列取出消息。它也可以實現了串行訪問共享資源,把訪問消息排隊,并且在稍后處理,這避免了共享資源同時訪問的問題。

1.5.1 模式結構

QUEUE_SIZE聲明決定隊列能容納最大的元素數目。必須足夠大來處理最差的情況,也不要太大以免內存的浪費。

1.5.2 角色

1.5.2.1 消息(Message)

它可以任何東西,是簡單的數據值,或發(fā)送消息的詳細數據報結構。

1.5.2.2 消息隊列(MessageQueue)

MessageQueue是QTasks間交換的信息存儲。提供了getNextIndex()函數來運行計算下一個有效的索引值。insert()函數在頭部位置將Message插入到隊列中并更新頭索引。remove()函數可以用于刪除最舊的消息。iFull(),isEmpty()兩個用來檢測隊列是否已滿,是否為空。

1.5.2.3 互斥信號量(Mutex)

是互斥信號量,如靜態(tài)優(yōu)先級模式中的描述類似。

1.5.2.4 任務(QTask)

QTask是MessageQueue的客戶,要么調用insert()插入新消息,要么調用remove()訪問最早的數據。

1.5.3 效果

當數據在任務間傳遞,隊列模式十分好用?;コ饬靠梢源_保隊列本身不會由于同時訪問造成損壞。相比守衛(wèi)調用模式,隊列模式接收數據不是很及時。

1.5.4 實現

隊列的最簡單實現是消息元素數組。有簡單的優(yōu)點,也會有靈活性不足,占用空間固定等缺陷。更多是使用鏈表的方式來實現隊列。MessageQueue還可以添加多個緩沖區(qū),每個優(yōu)先級一個隊列,這樣實現優(yōu)先級策略,或者基于消息優(yōu)先級,通過插入元素隊列中實現。在復雜的系統中,預測最佳隊列大小是不可行的,如果使用數組實現隊列的方式,會存在超出容量的問題。在這種情況下,可以額外使用一個緩沖隊列在作為臨時存儲。

1.6 匯合模式

任務必須以不同的方式同步。發(fā)生同步可能是共享單一資源,或者等待信號量等造成,這些隊列模式和守衛(wèi)調用模式都能夠實現。但是如果同步需要的條件更加復雜呢?匯合模式就是解決這個問題。當所有的任務都滿足同步條件時,才能繼續(xù)運行。

1.6.1 模式結構

需要同步的線程至少2個,同時擁有唯一的Rendezvous。

1.6.2 角色

1.6.2.1 聚合(Rendezvous)

用于管理同步。它通過兩個方式:reset()函數重置同步標準為初始條件。synchronize()函數,當任務想要同步時調用這個方法。如果不滿足標準,則任務阻塞。這個通??梢允褂糜^察者模式或守衛(wèi)調用模式實現。

1.6.2.2 計數信號量(Semaphore)

這個通常是計數信號量,有創(chuàng)建,摧毀,上鎖和釋放標準鎖的接口函數。用于存儲當前所有任務滿足同步條件的數量。當等于預設值時,同步條件滿足。

1.6.2.3 線程(SynchronizingThread)

代表使用Rendezvous同步的每個線程。

1.6.3 效果

在這個模式中,兩個或更多的任務都同時滿足某個條件時,才能繼續(xù)運行或調用回調函數。

1.6.4 實現

該模式可以通過前面的觀察者模式,或者守衛(wèi)調用模式實現。如果使用的是觀察者模式,則任務必須使用函數的地址注冊,當滿足同步條件時調用。如果使用的是守衛(wèi)調用模式,則每個Rendezvous對象擁有唯一的信號量,任務想同步時調用synchronize()函數告知給Rendezvous,當Rendezvous滿足同步條件時,釋放信號量,并且任務隨后根據通常的調度策略全部釋放運行。

1.7 同時鎖定模式

首先不考慮軟件自身導致的錯誤,發(fā)生死鎖需要滿足4個條件:

  1. 互斥鎖資源。

  2. 當請求其他資源時,一些資源已經鎖定。

  3. 當資源鎖定是允許搶斷。

  4. 存在循環(huán)等待條件。

死鎖能夠通過打破這4個條件的任意一個避免。使用臨界區(qū)模式打破的是條件1和條件3。隊列模式避免了條件1的發(fā)生。

同時鎖定模式是通過破壞條件2達到避免死鎖的目的。模式以全或無的形式工作。要么所有需要的資源一次都鎖定,要么都沒有鎖定。簡單來說在線程需要某個資源的時候,只有把所有的資源都一起上鎖成功,才能成功往下執(zhí)行,這樣就避免了兩個線程都在請求對方的資源造成的死鎖。

1.7.1 模式結構

一般來說,MultimasteredResource是不同資源集合的任意數目的一部分,其中ResourceMaster的單獨實例管理一個這樣的集合。

1.7.2 角色

1.7.2.1 資源管理(MultimateredResource)

這個元素通過多個ResourceMasters管理,然后他有自己的互斥信號量來避免同時申請鎖。使用QueryMutex必須通過tryLock()函數,以便能夠通過ResourceMasters決定所有的嘗試鎖定將會是成功或者失敗。

1.7.2.2 互斥量(QueryMutex)

這個算數是一個正常的互斥信號量,與之前的不用,它提供了tryLock()函數。這個函數和lock()函數目的是一樣的,都是為了上鎖,只是tryLock()函數除此之外,如果鎖失敗,他將會返回一個錯誤代碼,而不是阻塞當前的線程。

1.7.2.3 客戶(ResourceClient)

這個元素是一個客戶,想要一次訪問所有資源集合來避免死鎖。它直接訪問MultimateredResource,直到成功接收到ResourceMaster上的鎖。在使用完資源后釋放。

1.7.2.4 控制鎖(ResourceMaster)

ResourceMaster控制整個資源合集的鎖。

1.7.3 效果

同時鎖定模式通過消除必要條件2,通過一次鎖定所有需要的資源或一個都不鎖防止死鎖。但是這樣會增加了其他任務執(zhí)行的延時,而且很可能發(fā)生在甚至沒有實際資源的沖突下。在資源更多,更廣泛時出現這種情況更明顯。此外,模式不能解決優(yōu)先級倒置問題,事實上可能更嚴重。

1.7.4 實現

需要保證tryLock()函數錯做之前確保成功鎖定MultimasteredResource。

1.8 排序鎖定

排序鎖定是另一種確保死鎖不會發(fā)生的方法,這次是用過防止條件4發(fā)生。通過對資源排序,并且需要客戶總是按照那個指定的順序鎖定資源,這樣就不可能形成循環(huán)等待條件。

1.8.1 模式結構

1.8.2 角色

1.8.2.1 鎖(Mutex)

與上面的模式一樣,提供兩個基本的函數lock()和release()。

1.8.2.2 資源管理(OrderedResource)

這個是模式的核心。它有resourceID屬性,是一個唯一的與每個資源關聯的ID,并且與ResourceList關聯。這個類執(zhí)行的排序鎖定規(guī)則永遠是:如果資源的resourceID大于任意已鎖定資源最大的resourceID,則資源僅能被鎖定。ResourceClient首先需要調用lockDyadic(),然后添加到資源列表中,在對資源操作完成之后,調用releaseDyadic()函數。書上把這種訪問稱作為二元的,與二元不一樣的一元,差異在一元是在內部完成上鎖,使用資源,解鎖。而二元是可以保持在鎖的狀態(tài),等到資源使用完之后在釋放。

1.8.2.3 客戶(ResourceClient)

代表了想要調用OrderedResource服務的元素集合。對于客戶,不需要知道關于resourceID本身的任何東西。

1.8.2.4 資源列表(ResourceList)

在這個元素里,如果傳遞的resourceID大于已鎖定資源的最大一個,則addLock()返回成功。否則返回失敗。

1.8.2.5 已使用資源(ResourceReference)

這僅是一個在有序列表中包含的resourceID數組。只是保存一個最大值是不夠的,因為很多資源可能在任何時候鎖定。

1.8.3 效果

模式通過確保所有的客戶按相同的順序鎖定資源來消除死鎖。這個模式需要在設計時做好分析來規(guī)劃好資源的排序。例如現在有兩個線程,都需要用到資源A,B,C,如果線程1按A,B,C的順序鎖定,線程2按C,B,A的順序鎖定,就有可能發(fā)生死鎖。因此該模式就是為了讓資源都按照規(guī)定的序列來鎖定。

1.8.4 實現

模式的實現需要給每個OrderedResource增加額外的resourceID,并且在ResourceList的邏輯中確保每個OrderedResource的resourceID大于任意當前所的resourceID。還有,已經上鎖的resourceID的列表必須維護,當OrderedResource釋放時,可以適當地鎖定其他。

ResourceList最常見的實現是一個按照鎖定順序表示的resourceID整形數組。

免責聲明:本文內容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯系我們,謝謝!

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯系該專欄作者,如若文章內容侵犯您的權益,請及時聯系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或將催生出更大的獨角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數字化轉型技術解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關鍵字: AWS AN BSP 數字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術公司SODA.Auto推出其旗艦產品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關鍵字: 汽車 人工智能 智能驅動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據媒體報道,騰訊和網易近期正在縮減他們對日本游戲市場的投資。

關鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數據產業(yè)博覽會開幕式在貴陽舉行,華為董事、質量流程IT總裁陶景文發(fā)表了演講。

關鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數據產業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數字世界的話語權最終是由生態(tài)的繁榮決定的。

關鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經營業(yè)績穩(wěn)中有升 落實提質增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領增長 以科技創(chuàng)新為引領,提升企業(yè)核心競爭力 堅持高質量發(fā)展策略,塑強核心競爭優(yōu)勢...

關鍵字: 通信 BSP 電信運營商 數字經濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術學會聯合牽頭組建的NVI技術創(chuàng)新聯盟在BIRTV2024超高清全產業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現場 NVI技術創(chuàng)新聯...

關鍵字: VI 傳輸協議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯合招商會上,軟通動力信息技術(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關鍵字: BSP 信息技術
關閉
關閉