天天看點

UCOS學習筆記(六)信号量信号量

前言

這是用markdown寫的第一篇部落格,如果寫的不好見諒啦

信号量

基本概念及一些注意事項

将信号量用于同步的概念是荷蘭的電腦科學家Edgser Dijkstra 在1959 年發明的。在電腦軟體中,信号量是一種用于多任務排程的協定機制。

信号量像是一種上鎖機制,代碼必須獲得相應的鑰匙才能繼續執行,一旦獲得了鑰匙就意味着該任務具有了進入被鎖部分代碼的權限。

信号量用于控制對共享資源的保護,但是現在基本用來做任務同步用

對共享資源保護的方法:關中斷、對任務排程器加鎖、使用信号量加鎖、mutex方式

注意:一般不使用關中斷的方式,除非任務十分簡短,因為關中斷是關閉所有的中斷,包含滴答定時器中斷,會使系統時鐘出現問題

一般有倆種類型的信号量:二值信号量和多值信号量。二值信号量的值隻能是0和1,多值信号量的值可以通過更改OS_SEM_CTR的定義修改為8、16、32位。

隻有任務才允許使用信号量,ISR是不允許的。

信号量是核心對象,通過資料類型OS_SEM定義,應用中可以有任意多個信号量。

等待信号量 Pend 發送或釋放信号量 Post

二進制信号量用于那些一次隻能有一個任務使用的資源,比如IO裝置

多值信号量用于某些資源可以被幾個任務來使用

資料類型

struct  os_sem {                                            /* Semaphore                                              */
                                                            /* ------------------ GENERIC  MEMBERS ------------------ */
    OS_OBJ_TYPE          Type;                              /* Should be set to OS_OBJ_TYPE_SEM                       */
    CPU_CHAR            *NamePtr;                           /* Pointer to Semaphore Name (NUL terminated ASCII)       */
    OS_PEND_LIST         PendList;                          /* List of tasks waiting on semaphore                     */
#if OS_CFG_DBG_EN > 0u
    OS_SEM              *DbgPrevPtr;
    OS_SEM              *DbgNextPtr;
    CPU_CHAR            *DbgNamePtr;
#endif
                                                            /* ------------------ SPECIFIC MEMBERS ------------------ */
    OS_SEM_CTR           Ctr;
    CPU_TS               TS;
};
           

其中中間與調試有關的部分暫時不管

第一個為“Type”域,表明這定義的是一個信号量(UCOSIII每個核心對象都有Type域)

第二個為信号量的名字(UCOSIII每個核心對象都可以被賦予一個名字,為ASCII字元串組成,但必須以空字元結尾)

第三個為挂起隊列若有多個任務等待信号量,信号量就會将這些任務放入其挂起隊列中

OS_SEM_CTR為信号量中包含的一個信号量計數變值(若為1該信号量為二值信号量,若不為1該信号量為多值信号量)

最後一個是系統時間戳。

相關API函數

函數名 作用
OSSemCreat() 建立一個信号量
OSSemDel 删除一個信号量
OSSemPend() 等待一個信号量
OSSemPendAbrot() 取消等待
OSSemPost() 釋放或者發出一個信号量
OSSemSet() 強制設定一個信号量

其中重點标注的三個API便是常用的三個,不僅僅是信号量,内建信号量、互斥信号量(Mutex)、内建互斥信号量消息隊列也是一般隻是用Create、Pend、Post三個函數。

注意事項

用信号量通路共享資源不會導緻中斷延遲。當任務在執行信号量所保護的共享資源時,ISR 或高優先級任務可以搶占該任務。

應用中可以有任意個信号量用于保護共享資源。然而,推薦将信号量用于I/O 端口的保護,而不是記憶體位址。

信号量經常被過度使用。很多情況下,通路一個簡短的共享資源時不推薦使用信号量,請求和釋放信号量會消耗CPU 時間。通過關/開中斷能更有效地執行這些操作。為了說明,假設兩個任務共享一個32 位的整數變量。第一個任務将這個整數變量加1,第二個任務将這個變量清零。考慮到執行這些操作用時很短,不需要使用信号量。執行這個操作前任務隻需關中斷,執行完畢後再開中斷。若操作浮點數變量且處理器不支援硬體浮點操作時,就需要用到信号量。因為在這種情況下處理浮點數變量需較長時間。

信号量會導緻一種嚴重的問題:優先級反轉。

對于如何處理優先級翻轉就需要使用互斥信号量了

繼續閱讀