在基于RTOS開發項目時,通常都會遇到互斥的情況,比如:幾個任務都要使用一個UART串口進行發送數據。
如果不加互斥鎖,優先級高的任務,會搶占串口并發送數據,則有可能會出現發送數據“亂碼”的情況。
今天就說說在RTOS開發中,互斥鎖一個常見的問題。
什么是Mutex互斥鎖?
學習過RTOS的讀者應該對互斥不陌生,互斥鎖就是為了避免任務之間互相搶占某種資源而設計的一種“鎖”。
就如上面說的,一個串口,被兩個任務搶占,如果不加鎖,則會出現兩個任務交叉發送數據,即“亂碼”;
但是,如果加了互斥鎖,則會等待其他任務發送完成之后才繼續發送,保證了數據的完整(而不是亂碼);
Mutex互斥鎖例子
這里以三個任務、兩個互斥鎖為例,代碼如下:
void task1()
{
/*do something*/
OSMutex1_Pend(); //互斥鎖1加鎖
/*加鎖處理事情*/
OSMutex1_Post(); //互斥鎖1解鎖
}
void task2()
{
/*do something*/
OSMutex1_Pend(); //互斥鎖1加鎖
OSMutex2_Pend(); //互斥鎖2加鎖
/*加鎖處理事情*/
OSMutex2_Post(); //互斥鎖2解鎖
OSMutex1_Post(); //互斥鎖1解鎖
}
void task3()
{
/*do something*/
OSMutex2_Pend(); //互斥鎖2加鎖
/*加鎖處理事情*/
OSMutex2_Post(); //互斥鎖1解鎖
}
這樣設計,大家看出問題了嗎?
老司機應該看出來了,新手可能摸不著頭腦。
在任務2中,進行了2次加鎖、解鎖,而且“環環相扣”。
Mutex互斥鎖問題
假如任務1、 任務2、 任務3優先級分別為:1、 2、 3。
優先級順序就是:任務1 > 任務2 > 任務3(數字越小代表任務優先級越高)。
假設:任務1和任務2處于等待事件狀態,也就是處于阻塞狀態, task 3 處于運行狀態。
當任務3在“加鎖處理事情”的時候,任務2搶占了任務3(任務2掛起時間到了),此時任務3掛起,任務2處于運行狀態;
如果任務2在“互斥鎖1加鎖”之后,任務1搶占了任務2,此時,任務1處于運行狀態;
這個時候,你發現問題了沒有?
任務1在執行“OSMutex1_Pend();”會等待“互斥鎖1解鎖”,如果其他方式沒有對“互斥鎖1解鎖”,則會出現“死鎖”的情況。
分享一張圖片,你就會明白什么是死鎖了:
解決辦法
比如對任務2加鎖方式進行改善:
void task2()
{
/*do something*/
OSMutex1_Pend(); //互斥鎖1加鎖
/*do something*/
OSMutex1_Post(); //互斥鎖1解鎖
OSMutex2_Pend(); //互斥鎖2加鎖
/*do something*/
OSMutex2_Post(); //互斥鎖1解鎖
}
或者對低優先級的任務3加鎖方式進行改善:
void task3()
{
/*do something*/
OSMutex1_Pend(); //互斥鎖1加鎖
OSMutex2_Pend(); //互斥鎖2加鎖
/*加鎖處理事情*/
OSMutex2_Post(); //互斥鎖2解鎖
OSMutex1_Post(); //互斥鎖1解鎖
}
出問題的原因, 當一個任務獲得了臨界區資源的鎖,在沒有釋放這個鎖的前提下又去獲得另外一塊臨界區資源,這個時候就要引起足夠的注意了,設計成敗在于你是否徹底理解了之前的問題。
但是,歸根到底這樣的問題還是要求用戶在設計階段去避免,一個系統不可能是萬能的,正確的設計才是最重要的。
原文標題:RTOS 任務間互斥的難題
文章出處:【微信公眾號:strongerHuang】歡迎添加關注!文章轉載請注明出處。
審核編輯:湯梓紅
-
串口
+關注
關注
14文章
1543瀏覽量
76187 -
RTOS
+關注
關注
21文章
809瀏覽量
119431
原文標題:RTOS 任務間互斥的難題
文章出處:【微信號:strongerHuang,微信公眾號:strongerHuang】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論