在操作系統(tǒng)系統(tǒng)中,信號量通常用于控制對共享資源的訪問和任務(wù)之間進(jìn)行同步,信號量在操作系統(tǒng)中是很常用的,也是學(xué)習(xí)freeRTOS操作系統(tǒng)必須要掌握的。
freeRTOS中最常用到的信號量有:二值信號量、計(jì)數(shù)信號量、互斥信號量。
有關(guān)這幾個信號量分別如下:
1、二值信號量
1.1、二值信號量
二值信號量是指所創(chuàng)建的信號量只有兩個值(0 和 1),通常用于互斥訪問或者同步。
二值信號量在某處被占有使用之后,其他地方想要申請這個二值信號量是無法成功申請的,只有當(dāng)這個被占有的二值信號量被使用完畢并釋放之后,才能被再次申請占有使用!
總而言之,二值信號量被使用之后會變?yōu)闊o效狀態(tài),需要被重新釋放才能進(jìn)入有效狀態(tài)。
在freeRTOS中,二值信號量的創(chuàng)建和使用的API管理函數(shù)分別如下:
1.2、創(chuàng)建二值信號量
函數(shù)原型:SemaphoreHandle_t xSemaphoreCreateBinary(void)
函數(shù)描述:
函數(shù)** xSemaphoreCreateBinary** 用于創(chuàng)建二值信號量。
返回值: 如果創(chuàng)建成功會返回二值信號量的句柄,創(chuàng)建失敗會返回 NULL。
1.3、等待二值信號量
在freeRTOS中,信號量的獲取是進(jìn)行了區(qū)分的,在任務(wù)或者函數(shù)中獲取與在中斷中是不一樣的,freeRTOS中給出了不同API函數(shù)。
1)在任務(wù)代碼中等待信號量
函數(shù)原型:
xSemaphoreTake( SemaphoreHandle_t xSemaphore, /* 信號量句柄 */
TickType_t xTicksToWait ); /* 等待信號量可用的最大等待時間 */
函數(shù)描述:
函數(shù) xSemaphoreTake 用于在任務(wù)代碼中獲取信號量。
第 1 個參數(shù)是信號量句柄。
第 2 個參數(shù)是沒有信號量可用時,等待信號量可用的最大等待時間,單位系統(tǒng)時鐘節(jié)拍。
返回值:如果創(chuàng)建成功會獲取信號量返回 pdTRUE,否則返回 pdFALSE。
使用這個函數(shù)要注意以下問題:
此函數(shù)是用于任務(wù)代碼中調(diào)用的,不可以在中斷服務(wù)程序中調(diào)用此函數(shù),中斷服務(wù)程序使用的是xSemaphoreTakeFromISR。
2)在中斷中等待信號量
xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken )
函數(shù)描述:
函數(shù)xSemaphoreTakeFromISR用于在中斷中獲取信號量。
第 1 個參數(shù)是要獲取的信號量的句柄。這是創(chuàng)建信號量時返回的句柄。
第 2 個參數(shù)是如果采用信號量導(dǎo)致任務(wù)取消阻止,并且未阻止的任務(wù)的優(yōu)先級高于當(dāng)前運(yùn)行的任務(wù),則xSemaphoreTakeFromISR()會將pxHigherPriorityTaskWoken設(shè)置為pdTRUE。
如果xSemaphoreTakeFromISR()將此值設(shè)置為pdTRUE,則應(yīng)在退出中斷之前請求上下文切換。
返回值:如果創(chuàng)建成功會獲取信號量返回 pdTRUE,否則返回 pdFALSE。
1.4、釋放二值信號量
1)用于在任務(wù)代碼中釋放二值信號量
函數(shù)原型:
xSemaphoreGive( SemaphoreHandle_t xSemaphore ); /* 信號量句柄 */
函數(shù)描述:釋放信號量
函數(shù) xSemaphoreGive 用于在任務(wù)代碼中釋放信號量。
第 1 個參數(shù)是信號量句柄。
返回值,如果信號量釋放成功返回 pdTRUE,否則返回 pdFALSE,因?yàn)樾盘柫康膶?shí)現(xiàn)是基于消息隊(duì)列,返回失敗的主要原因是消息隊(duì)列已經(jīng)滿了。
注意:此函數(shù)是用于任務(wù)代碼中調(diào)用的,不可以在中斷服務(wù)程序中調(diào)用此函數(shù)。
2)用于在中斷中釋放二值信號量
函數(shù)原型:
xSemaphoreGiveFromISR(SemaphoreHandle_t xSemaphore, signed BaseType_t *pxHigherPriorityTaskWoken)
函數(shù)描述:
函數(shù) xSemaphoreGiveFromISR 用于中斷服務(wù)程序中釋放信號量。
第 1 個參數(shù)是信號量句柄。
第2個參數(shù)用于保存是否有高優(yōu)先級任務(wù)準(zhǔn)備就緒。如果函數(shù)執(zhí)行完畢后,此參數(shù)的數(shù)值是pdTRUE,說明有高優(yōu)先級任務(wù)要執(zhí)行,否則沒有。
返回值:如果信號量釋放成功返回 pdTRUE,否則返回 errQUEUE_FULL。
2、計(jì)數(shù)信號量
計(jì)數(shù)信號量是一個相當(dāng)于長度大于1的隊(duì)列,用于任務(wù)之間的同步和共享資源的保護(hù)。
計(jì)數(shù)信號量與二值信號量的不同在于,二值信號量只能被一個地方申請使用,只有在這個申請使用的地方了釋放了才能被其他處申請使用。而計(jì)數(shù)信號量是可以創(chuàng)建一定數(shù)量的信號量的,多個地方可以同時申請使用,直到達(dá)到最大的計(jì)數(shù)信號量的閾值。
計(jì)數(shù)信號量相關(guān)的API函數(shù):
2.1、創(chuàng)建計(jì)數(shù)信號量
SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, /* 支持的最大計(jì)數(shù)值 */
UBaseType_t uxInitialCount); /* 初始計(jì)數(shù)值 */
第 1 個參數(shù):設(shè)置此計(jì)數(shù)信號量支持的 最大計(jì)數(shù)值 。
第 2 個參數(shù):設(shè)置計(jì)數(shù)信號量的 初始值 。(為0則不起作用)
返回值:如果創(chuàng)建成功會返回消息隊(duì)列的句柄,創(chuàng)建失敗會返回 NULL。
2.2、獲取信號量
1)在任務(wù)代碼中獲取信號量
xSemaphoreTake( SemaphoreHandle_t xSemaphore, /* 信號量句柄 */
TickType_t xTicksToWait ); /* 等待信號量可用的最大等待時間 */
函數(shù) xSemaphoreTake 用于在任務(wù)代碼中獲取信號量。
第 1 個參數(shù)是信號量句柄。
第 2 個參數(shù)是沒有信號量可用時,等待信號量可用的最大等待時間,單位系統(tǒng)時鐘節(jié)拍。
返回值:如果信號量獲取成功會返回 pdTRUE,否則返回 pdFALSE。
2)在中斷中獲取信號量
xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken )
函數(shù)描述:
函數(shù) **xSemaphoreTakeFromISR **用于在中斷中獲取信號量。
第 1 個參數(shù)是要獲取的信號量的句柄。這是創(chuàng)建信號量時返回的句柄。
第 2 個參數(shù)是如果采用信號量導(dǎo)致任務(wù)取消阻止,并且未阻止的任務(wù)的優(yōu)先級高于當(dāng)前運(yùn)行的任務(wù),則xSemaphoreTakeFromISR()會將pxHigherPriorityTaskWoken設(shè)置為pdTRUE。如果xSemaphoreTakeFromISR()將此值設(shè)置為pdTRUE,則應(yīng)在退出中斷之前請求上下文切換。
返回值,如果創(chuàng)建成功會獲取信號量返回 pdTRUE,否則返回 pdFALSE。
2.3、釋放信號量
1)在任務(wù)代碼中釋放信號量
xSemaphoreGive( SemaphoreHandle_t xSemaphore ); /* 信號量句柄 */
函數(shù) xSemaphoreGive 用于在任務(wù)代碼中釋放信號量。
第 1 個參數(shù)是信號量句柄。
返回值,如果信號量釋放成功返回 pdTRUE,否則返回 pdFALSE,因?yàn)橛?jì)數(shù)信號量的實(shí)現(xiàn)是基于消息隊(duì)列,返回失敗的主要原因是消息隊(duì)列已經(jīng)滿了。
2)在中斷中釋放信號量
xSemaphoreGiveFromISR(
SemaphoreHandle_t xSemaphore, /* 信號量句柄 */
signed BaseType_t *pxHigherPriorityTaskWoken /* 高優(yōu)先級任務(wù)是否被喚醒的狀態(tài)保存 */
)
第 1 個參數(shù)是信號量句柄。
第2個參數(shù)用于保存是否有高優(yōu)先級任務(wù)準(zhǔn)備就緒。如果函數(shù)執(zhí)行完畢后,此參數(shù)的數(shù)值是pdTRUE,說明有高優(yōu)先級任務(wù)要執(zhí)行,否則沒有。
返回值:如果信號量釋放成功返回 pdTRUE,否則返回 errQUEUE_FULL。
3、優(yōu)先級反轉(zhuǎn) & 互斥信號量
在實(shí)時操作系統(tǒng)中,優(yōu)先級反轉(zhuǎn)的問題是不容忽視的,程序設(shè)計(jì)的過程中,也是要充分考慮這個問題的。
那優(yōu)先級反轉(zhuǎn)到底是什么呢?
優(yōu)先反轉(zhuǎn)是指:假如一個系統(tǒng)中有高(H)、中(M)、低(L)三個優(yōu)先級的任務(wù),并有一個二值信號量。在某一個時刻二值信號量被低(L)優(yōu)先級的任務(wù)使用了,并在運(yùn)行過程中,高優(yōu)先級任務(wù)(H)搶占了低優(yōu)先級(L)的CPU使用權(quán),但是也想要獲取二值信號量被低優(yōu)先(L)的任務(wù)占有著,高優(yōu)先級任務(wù)(H)由此被掛起等待了,中優(yōu)先級任務(wù)(M)因?yàn)椴恍枰敌盘柫?,會搶占低?yōu)先級(L)任務(wù)的執(zhí)行而得到運(yùn)行,而高優(yōu)先級任務(wù)(H)依然只能等到低優(yōu)先級任務(wù)(L)釋放二值信號量才能得到執(zhí)行。
由此造成了高優(yōu)先級任務(wù)得不到及時的執(zhí)行,而低優(yōu)先級任務(wù)卻能比高優(yōu)先級任務(wù)更多的得到執(zhí)行。
優(yōu)先級互斥的示意圖如下:
解決優(yōu)先級反轉(zhuǎn)的問題最好的辦法是使用互斥信號量。
互斥信號量和二值信號量比較相似,不同之處在于互斥信號量具有優(yōu)先級繼承的特性,如果一個互斥信號量正在被一個低優(yōu)先級的任務(wù)使用,而此時這個高優(yōu)先級的任務(wù)也希望獲取這個互斥信號量的話就會被阻塞。
使用互斥信號量時,高優(yōu)先級的任務(wù)會把低優(yōu)先級的任務(wù)的優(yōu)先級先提高到和自己相同的優(yōu)先級,保證低優(yōu)先級的任務(wù)能夠繼續(xù)運(yùn)行至結(jié)束這樣極大減少了因?yàn)楦邇?yōu)先級獲取不到信號量被阻塞過長時間的問題。
互斥信號量的API函數(shù):
1)創(chuàng)建互斥信號量
函數(shù)原型:
SemaphoreHandle_t xSemaphoreCreateMutex(void)
函數(shù)描述:
函數(shù) xSemaphoreCreateMutex 用于創(chuàng)建互斥信號量。
返回值:如果創(chuàng)建成功會返回互斥信號量的句柄,失敗會返回 NULL。
2)獲取互斥信號量
函數(shù)原型:
xSemaphoreTake( SemaphoreHandle_t xSemaphore, /* 信號量句柄 */
TickType_t xTicksToWait ); /* 等待信號量可用的最大等待時間 */
函數(shù)描述:
函數(shù) xSemaphoreTake 用于在任務(wù)代碼中獲取信號量。
第 1 個參數(shù)是信號量句柄。
第 2 個參數(shù)是沒有信號量可用時,等待信號量可用的最大等待時間,單位系統(tǒng)時鐘節(jié)拍。
返回值:如果創(chuàng)建成功會獲取信號量返回 pdTRUE,否則返回 pdFALSE。
(2)釋放互斥信號量
函數(shù)原型:
xSemaphoreGive( SemaphoreHandle_t xSemaphore ); /* 信號量句柄 */
函數(shù)描述:
函數(shù) xSemaphoreGive 用于在任務(wù)代碼中釋放信號量。
第 1 個參數(shù)是信號量句柄。
返回值:如果信號量釋放成功返回 pdTRUE,否則返回 pdFALSE,因?yàn)樾盘柫康膶?shí)現(xiàn)是基于消息隊(duì)列,返回失敗的主要原因是消息隊(duì)列已經(jīng)滿了。
-
操作系統(tǒng)
+關(guān)注
關(guān)注
37文章
6898瀏覽量
123784 -
FreeRTOS
+關(guān)注
關(guān)注
12文章
484瀏覽量
62410 -
信號量
+關(guān)注
關(guān)注
0文章
53瀏覽量
8376
發(fā)布評論請先 登錄
相關(guān)推薦
FreeRTOS信號量使用教程
![<b class='flag-5'>FreeRTOS</b><b class='flag-5'>信號量</b>使用教程](https://file.elecfans.com/web2/M00/81/75/poYBAGORrvKAICobAAA8qMyyPR0245.jpg)
FreeRTOS信號量的使用與實(shí)例
轉(zhuǎn):freeRTOS信號量學(xué)習(xí)
freertos用信號量同步的時候多任務(wù)運(yùn)行老是崩潰的原因?
FreeRTOS信號量介紹
FreeRTOS信號量 & ESP32實(shí)戰(zhàn)
![<b class='flag-5'>FreeRTOS</b><b class='flag-5'>信號量</b> & ESP32實(shí)戰(zhàn)](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
FreeRTOS 隊(duì)列 信號量 互斥量
![<b class='flag-5'>FreeRTOS</b> 隊(duì)列 <b class='flag-5'>信號量</b> 互斥<b class='flag-5'>量</b>](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
FreeRTOS高級篇6---FreeRTOS信號量分析
![<b class='flag-5'>FreeRTOS</b>高級篇6---<b class='flag-5'>FreeRTOS</b><b class='flag-5'>信號量</b>分析](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
FreeRTOS系列第20篇---FreeRTOS信號量API函數(shù)
![<b class='flag-5'>FreeRTOS</b>系列第20篇---<b class='flag-5'>FreeRTOS</b><b class='flag-5'>信號量</b>API函數(shù)](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
在Arduino IDE中使用FreeRTOS信號量
![在Arduino IDE中使用<b class='flag-5'>FreeRTOS</b><b class='flag-5'>信號量</b>](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
評論