天天看點

學習FreeRTOS之第七章——資源管理

一,在多任務作業系統中,當一個任務通路一個資源時,在沒有通路完成的情況下,任務切換出運作狀态。這時,可能會出現資料損壞等問題。看看下面幾種情況:

1,通路外圍裝置。例如:兩個任務寫資料到LCD,任務A寫“Hello,world”到LCD,在任務A未寫完的情況下,任務B搶占了任務A,任務B寫其他的資料到LCD,這時LCD會顯示錯誤。

2,常見的“讀,修改,寫”三步操作。

3,對變量的非原子通路。例如:當結構體或者變量大于CPU架構的字大小時,對該結構體或者變量進行通路(在16位的機器上,對32的變量進行寫操作)。

4,函數的重入。例如:下面的函數是不可重入的。

學習FreeRTOS之第七章——資源管理

二, 為了解決上面的問題,FreeRTOS提供了很多解決方法,但是最好的方法是在進行應用程式設計時,使資源不在任務之間進行共享,并且每個任務隻能通路一個資源。

1,臨界段保護

使用taskENTER_CRITICAL()/taskEXIT_CRITICAL()和taskENTER_CRITICAL_FROM_ISR()/taskEXIT_CRITICAL_FROM_ISR()。臨界段保護是一個宏,根據configMAX_SYSCALL_INTERRUPT_PRIORITY的設定,要麼完全禁止了中斷或者禁止configMAX_SYSCALL_INTERRUPT_PRIORITY設定優先級以上的中斷。理想使用情況是臨界段間的代碼越短越好。可以嵌套使用。

2,挂起排程器

使用vTaskSuspendAll()和xTaskResumeAll()來保護資源。這種方式可以避免任務切換,但是中斷仍然在工作。挂起排程器可以嵌套,任務排程器挂起時,不能調用API函數。

3,互斥信号量

使用互斥信号量需要将configUSE_MUTEXES設定為1。當任務要通路一個資源時,首先要獲得互斥信号量,通路完成時,釋放該互斥信号量。

學習FreeRTOS之第七章——資源管理
學習FreeRTOS之第七章——資源管理

在上面的執行過程中出現了任務優先級反轉的問題,高優先級的Task2等待低優先級的Task1。在最差的情況下,如果有一個介于任務2和任務1之間優先級的其他任務,這時,任務2會一直等待,甚至任務1都不會執行。

為了解決優先級反轉問題,互斥信号量引入了優先級繼承,這也是互斥信号量和二進制信号量的一個不同點。擁有互斥信号量的低優先級任務會繼承等待該互斥信号量的任務中最高優先級,并在釋放該互斥信号量時,複位優先級。互斥信号量不能在ISR中使用。

學習FreeRTOS之第七章——資源管理

 在使用互斥信号量時,當兩個任務都在等待對方的資源釋放時,可能會發生死鎖現象。避免死鎖的最好方法是在設計時,避免死鎖發生,尤其是在等待信号量時,不要設定為死等。

4,遞歸互斥信号量

當一個任務在沒有釋放信号量的情況下,擷取兩次信号量,會造成自鎖。這種情況可以通過使用遞歸互斥信号量替代标準互斥信号量。

學習FreeRTOS之第七章——資源管理

 在使用互斥信号量的應用中,如果兩個任務優先級相同,可能會出現其中一個任務的運作時間不如預期時間,例如:

學習FreeRTOS之第七章——資源管理

5,守護任務

守護任務是一個唯一對資源擁有所有權的任務,隻有守護任務能夠直接通路資源。其他任務要通路該資源,需要通過守護任務提供的服務進行間接通路。

繼續閱讀