1. 程式人生 > >FreeRTOS-互斥訊號量

FreeRTOS-互斥訊號量

原文地址:http://blog.csdn.net/xukai871105/article/details/43456985

0.前言

    在嵌入式作業系統中互斥型訊號量是任務間資源保護的重要手段。下面結合一個具體例子說明FreeRTOS中的互斥型訊號量如何使用。

1.基本說明     互斥型訊號量的使用方法如圖1所示。在多數情況下,互斥型訊號量和二值型訊號非常相似,但是從功能上二值型訊號量用於同步,而互斥型訊號量用於資源保護。互斥型訊號量和二值型訊號量還有一個最大的區別,互斥型訊號量可以有效解決優先順序反轉現象。
圖1 互斥型訊號量使用方法 (1)互斥訊號量的簡介 在互斥訪問中互斥訊號量相當於一個鑰匙,當任務想要使用資源的時候就必須先獲得這個鑰匙,當使用完資源以後就必須歸還這個鑰匙,這樣其他的任務就可以拿著這個鑰匙去使用資源.
(2)優先順序繼承 當一個互斥訊號量正在被一個低優先順序的任務使用,而此時有個高優先順序的任務也嘗試獲取這個這個互斥訊號量的話就會被阻塞。不過這個高優先順序的任務會將低優先順序的任務的優先順序提升到與自己相同優先順序,這個過程就是優先順序繼承。 優先順序繼承儘可能降低了高優先順序任務處於阻塞態的時間,並將已經出現的“優先順序翻轉的影響降低到最低. (3)互斥訊號量不能用在中斷服務函式中,原因如下: 互斥訊號量具有優先順序繼承機制,所以只能用在任務中,不能用在中斷服務函式中。 中斷服務函式中不能因為要等待互斥訊號量而設定阻塞時間進入阻塞態。 (4)二值訊號量 與 互斥訊號量的區別 互斥訊號量擁有優先順序繼承機制,二值訊號量沒有優先順序繼承機制
二值訊號量更加適合用於任務同步,互斥訊號量更加適合用於互斥訪問

2.參考程式碼

    本例具有兩個任務,兩個任務都試圖通過串列埠列印內容,此時串列埠就好比一個“資源”,某個任務使用串列埠資源時必須保護該資源,使用完串列埠之後在釋放資源。保護和釋放動作便對應互斥型訊號量的兩個基本操作,xSemaphoreTake和xSemaphoreGive。     【程式碼】
/* Standard includes. */
#include <stdio.h>
#include <string.h>

/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"

/* Library includes. */
#include "stm32f10x.h"

#define LED0_ON()   GPIO_SetBits(GPIOB,GPIO_Pin_5);
#define LED0_OFF()  GPIO_ResetBits(GPIOB,GPIO_Pin_5);

static void Setup(void);
void TaskA( void *pvParameters );
void TaskB( void *pvParameters );

void LedInit(void);
void UART1Init(void);

/* 互斥訊號量控制代碼 */
SemaphoreHandle_t xSemaphore = NULL;

int main(void)
{
    /* 初始化硬體平臺 */
    Setup();
    /* 建立互斥訊號量 */
    xSemaphore = xSemaphoreCreateMutex();
    /* 建立任務 */
    xTaskCreate( TaskA, "TaskA", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY+3, NULL );
    xTaskCreate( TaskB, "TaskB", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY+4, NULL );
    /* 啟動OS */
    vTaskStartScheduler();
    
    return 0;
}

void TaskA( void *pvParameters )
{
    for( ;; )
    {
        xSemaphoreTake( xSemaphore, portMAX_DELAY );
        {
            printf("Task A\r\n");
        }
        xSemaphoreGive( xSemaphore );
        vTaskDelay( 2000/portTICK_RATE_MS );
    }
}

void TaskB( void *pvParameters )
{
    for( ;; )
    {
        xSemaphoreTake( xSemaphore, portMAX_DELAY );
        {
            printf("Task B\r\n");
        }
        xSemaphoreGive( xSemaphore );
        vTaskDelay( 1000/portTICK_RATE_MS );
    }
}

static void Setup( void )
{
    LedInit();
    UART1Init();
}

void LedInit( void )
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
    /*LED0 @ GPIOB.5*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init( GPIOB, &GPIO_InitStructure );    
}

void UART1Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    
    /* 第1步:開啟GPIO和USART時鐘 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
    
    /* 第2步:將USART1 
[email protected]
的GPIO配置為推輓複用模式 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* 第3步:將USART1 [email protected]的GPIO配置為浮空輸入模式 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* 第4步:配置USART1引數 波特率 = 9600 資料長度 = 8 停止位 = 1 校驗位 = No 禁止硬體流控(即禁止RTS和CTS) 使能接收和傳送 */ USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure); /* 第5步:使能 USART1, 配置完畢 */ USART_Cmd(USART1, ENABLE); /* 清除傳送完成標誌 */ USART_ClearFlag(USART1, USART_FLAG_TC); /* 使能USART1傳送中斷和接收中斷,並設定優先順序 */ NVIC_InitTypeDef NVIC_InitStructure; // NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); /* 設定USART1 中斷優先順序 */ NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configLIBRARY_KERNEL_INTERRUPT_PRIORITY; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* 使能接收中斷 */ // USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); } int fputc(int ch, FILE *f) { /* 寫一個位元組到USART1 */ USART_SendData(USART1, (uint8_t) ch); /* 等待發送結束 */ while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET) {} return ch; }

3.簡單說明 SemaphoreHandle_t xSemaphore = NULL;     申明互斥型訊號量,在FreeRTOS中二值型訊號量和互斥型訊號量型別完全相同。 xSemaphore = xSemaphoreCreateMutex();     建立互斥型訊號量。 xSemaphoreTake( xSemaphore, portMAX_DELAY );     獲得資源的使用權,此處的等待時間為portMAX_DELAY(掛起最大時間),如果任務無法獲得資源的使用權,任務會處於掛起狀態。  xSemaphoreGive( xSemaphore );     釋放資源的使用權。 4.總結     互斥型訊號量和二值型訊號量使用方法相似,但二值型訊號量用於同步而互斥型訊號量用於資源保護。

相關推薦

FreeRTOS-互斥訊號

原文地址:http://blog.csdn.net/xukai871105/article/details/43456985 0.前言     在嵌入式作業系統中互斥型訊號量是任務間資源保護的重要手段。下面結合一個具體例子說明FreeRTOS中的互斥型訊號量如何使用。

Python多程序,同步互斥,訊號,鎖補充上一篇文章

from multiprocessing import Event,Process from time import sleep def wait_event1(): print("1想操作臨界區資源") e.wait() print("1開始操作臨界區資源",e.is_set()

互斥訊號

---關鍵程式碼如下--- void CTestSemaphoreDlg::OnBnClickedButtonThread1() {     // TODO: 在此新增控制元件通知處理程式程式碼     AfxBeginThread((AFX_THREADPROC)thre

uc/os-iii學習筆記-資源管理(中斷、訊號訊號互斥訊號

資源管理 最常用的獨佔共享資源和建立臨界區的方法有以下幾種: 關、開中斷 獨佔共享資源最簡單也是最快捷的方法就是關中斷和開中斷,當訪問共享資源的速度很快,以至於訪問共享資源所花的時間小於中斷的關閉時間時,可以使用關、開中斷方法。但是不推薦此方法

UCOSIII訊號互斥訊號

在UCOSIII中可能會偶多個任務會訪問共享資源,因此訊號量最早用來控制任務存取共享資源,現在訊號量也被用來實現任務間的同步以及任務和ISP同步。在可剝奪的核心中,當任務獨佔式使用共享資源的時候,會低優的任務高於高階優先任務執行的現象,這個現象叫做優先順序反轉,

vxWorks互斥訊號示例

#include "vxWorks.h" #include "semLib.h" #include "taskLib.h" #include "logLib.h" #include "sysLib.h" #include "stdio.h" #define CON

pthread互斥訊號使用總結

----一年前寫的東西,重新抄錄以防遺忘。 glibc提供的pthread互斥訊號量可以用在程序內部,也可以用在程序間,可以在初始化時通過pthread_mutexattr_setpshared介面設定該訊號 量屬性,表示是程序內還是程序間。程序內的使用較為簡單,本文

ucosIII 共享資源(訊號互斥訊號

共享資源: 變數(靜態或全域性變數)、資料結構體、RAM表格、I/O裝置等。OS在使用一些資源時候,例如IO裝置印表機,當任務1在使用印表機時候必須保證資源獨享,避免其他任務修改列印內容導致出錯,因此需要有資源共享機制。 一般推薦使用互斥訊號量對共享資源實現

UCOS2:對於訊號互斥訊號,事件標誌組

2.訊號量:    至於訊號量,和互斥訊號量是用區別的,簡單來說(個人理解,歡迎糾正)就是互斥訊號量再同一時刻,任務得到互斥訊號量量後是獨佔共享資源的,在他沒有釋放訊號量之前,任何其他任務都是不能訪問共享資源的。而訊號量的不同在於。訊號量可以設定一個值,允許最多又幾個任務同時去訪問共享資源。比如我給他設定一個

【UCOSIII】UCOSIII的互斥訊號

訊號量用於控制對共享資源的保護,但是現在基本用來做任務同步用(不太清楚的可以參考連結:【UCOSIII】UCOSIII的訊號量)。優先順序反轉優先順序反轉在可剝奪核心中是非常常見的,在實時系統中不允許出現這種現象,這樣會破壞任務的預期順序,可能會導致嚴重的後果,下圖就是一個優

FreeRTOS 學習五:訊號互斥

1. 簡介: 此篇文章中涉及的函式除特殊說明,包含的標頭檔案都是 semphr.h 二值訊號量同linux中的原子量,我們可以看成像是一個鎖,在使用的時候,需要能拿到鎖才能執行程式,嘗

FreeRTOS學習筆記——互斥訊號

/* Standard includes. */ #include <stdio.h> #include <string.h> /* Scheduler includes. */ #include "FreeRTOS.h" #include "task.h" #include "qu

[領卓教育]執行緒的同步與互斥機制——訊號

訊號量的初始化 int sem_init(sem_t *sem, int pshared, unsigned int value); 功能: 初始化訊號量 引數: sem :要是初始化的訊號量  pshared: 訊號量共享的範圍(0: 執行緒間使用 非0:程序間使用) value : 初始

作業系統 自旋鎖+訊號+互斥+臨界區+死鎖的區別

自旋鎖(SpinLock) 自旋鎖是專為防止多處理器併發而引入的一種鎖。如果是單核處理器,則自旋鎖定義為空操作,因為簡單的關閉中斷即可實現互斥。   自旋鎖最多隻能被一個執行緒持有,如果一個執行緒試圖請求一個已被爭用(已被另一個執行緒持有)的自旋鎖,那麼等待自旋鎖的執行緒將會反

Linux多執行緒程式設計---執行緒間同步(互斥鎖、條件變數、訊號和讀寫鎖)

本篇博文轉自http://zhangxiaoya.github.io/2015/05/15/multi-thread-of-c-program-language-on-linux/ Linux下提供了多種方式來處理執行緒同步,最常用的是互斥鎖、條件變數、訊號量和讀寫鎖。  下面是思維導

【Qt開發】QThread中的互斥、讀寫鎖、訊號、條件變數

在gemfield的《從pthread到QThread》一文中我們瞭解了執行緒的基本使用,但是有一大部分的內容當時說要放到這片文章裡討論,那就是執行緒的同步問題。關於這個問題,gemfield在《從進 程到執行緒》中有一個比喻,有必要重新放在下面溫習下: ***************

自旋鎖、互斥體和訊號

自旋鎖 Linux核心中最常見的鎖是自旋鎖(spin lock)。自旋鎖最多隻能被一個可執行執行緒持有。如果一個執行執行緒試圖獲得一個被已經持有的自旋鎖,那麼該執行緒就會一直進行忙迴圈——旋轉——等待鎖重新可用。要是鎖未被爭用,請求鎖的執行執行緒便能立刻得到它,繼續執行。在任意時間,自旋鎖都

使用互斥鎖mutex實現訊號sem

/* ======================== SYNCHRONISATION ========================= */ /* Init semaphore to 1 or 0 */ void bsem_init(bsem *bsem_p, int valu

訊號解決程序的同步與互斥

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

執行緒(三):Lock(互斥鎖)、RLock( 遞迴鎖)、Semaphore(訊號)、Event(事件)、Condition(條件)、Timer(定時器)、queue(佇列)

目錄 一、鎖 1)同步鎖 2)死鎖與遞迴鎖 二、訊號量 三、事件 四、條件 五、定時器 六、執行緒佇列 一、鎖 1)同步鎖 #同步鎖的引用 from threading import Thread,Lock import os,time def wor