FreeRTOS-互斥訊號量
原文地址:http://blog.csdn.net/xukai871105/article/details/43456985
0.前言
在嵌入式作業系統中互斥型訊號量是任務間資源保護的重要手段。下面結合一個具體例子說明FreeRTOS中的互斥型訊號量如何使用。
1.基本說明 互斥型訊號量的使用方法如圖1所示。在多數情況下,互斥型訊號量和二值型訊號非常相似,但是從功能上二值型訊號量用於同步,而互斥型訊號量用於資源保護。互斥型訊號量和二值型訊號量還有一個最大的區別,互斥型訊號量可以有效解決優先順序反轉現象。圖1 互斥型訊號量使用方法 (1)互斥訊號量的簡介 在互斥訪問中互斥訊號量相當於一個鑰匙,當任務想要使用資源的時候就必須先獲得這個鑰匙,當使用完資源以後就必須歸還這個鑰匙,這樣其他的任務就可以拿著這個鑰匙去使用資源.
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