旗號(semaphore)是一個允許線程等待某一事件直到此事件發生的同步原語,此事件可以有另一個線程產生,也可以有硬體中斷的DSR服 務函數產生。每一個旗號都有一個計數器與之對應,此計數器的數值表示關聯在此旗號上等待處理的事件個數。當計數器為零時,等待事件發生的線程被阻塞直到此 計數器大於零,等到事件後系統會對計數器減一;當事件發生後,系統對此計數器進行加一運算,表示等待處理的事件數目加一。
例如:有一批貨物要從A途徑B運到C處,其中此貨物由A運到B由X公司(相當於線程X)負責;此貨物由B運到C由Y公司(相當於線程Y)負責。X公司會將貨物一件一件的運到B處,B處每來一件貨物表示有一件貨物等待運走(相當於一個事件的產生並等待處理); B處貨物的個數相當於與此事件對應的旗號的計數器的數值。Y公司會將B處的貨物一件一件的運到C處,如果B處貨物件數大於0(此時相當於Y等待的事件發生過了),則Y公司將B處的一件貨物運到C處;如果B處沒有貨物則Y公司會一直等到X公司將貨物運到B為止。依次迴圈直到把A處的貨物全部運送到C處。
程式 :
#include <cyg/hal/hal_arch.h>
#include <cyg/kernel/kapi.h>
#include <stdlib.h>
#include <stdio.h>
#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
cyg_uint8 ThreadA_Stack[STACK_SIZE]; // 執行緒A的堆疊
cyg_handle_t ThreadA_Handle; // 執行緒A的句柄
cyg_thread ThreadA_Obj; // 執行緒A的信息結構體
cyg_uint8 ThreadB_Stack[STACK_SIZE]; // 執行緒B的堆疊
cyg_handle_t ThreadB_Handle; // 執行緒B的句柄
cyg_thread ThreadB_Obj; // 執行緒B的信息結構體
cyg_sem_t Sem_Get_Data; // 信號量定義
//====================================================
// 語法格式:void ThreadA(cyg_addrword_t data)
// 功能描述: 執行緒A
//====================================================
void ThreadA(cyg_addrword_t data)
{
while(1)
{
cyg_thread_delay(100);
cyg_semaphore_post(&Sem_Get_Data); // 發出信號量事件標志
printf("\nThreadA : A --> B"); // 打印信息
}
}
//===================================================
// 語法格式:void ThreadB(cyg_addrword_t data)
// 功能描述: 執行緒B
//====================================================
void ThreadB(cyg_addrword_t data)
{
while(1)
{
cyg_semaphore_wait(&Sem_Get_Data); // 等待Sem_Get_Data信號量事件標志
printf("\nThreadB : B --> C\n");
}
}
//====================================================
// 語法格式:void cyg_user_start(void)
// 功能描述: 主函數
//====================================================
void cyg_user_start(void)
{
cyg_semaphore_init(&Sem_Get_Data, 0); // 信號量初始化
cyg_thread_create(10, // 執行緒優先級
ThreadA, // 執行緒函數名
(cyg_addrword_t)0, // 執行緒參數
"Thread A", // 執行緒名稱
(void *)ThreadA_Stack, // 執行緒堆疊
STACK_SIZE, // 執行緒堆疊大小
&ThreadA_Handle, // 返回執行緒句柄
&ThreadA_Obj); // 執行緒信息結構體
cyg_thread_create(10, // 執行緒優先級
ThreadB, // 執行緒函數名
(cyg_addrword_t)0, // 執行緒參數
"Thread B", // 執行緒名稱
(void *)ThreadB_Stack, // 執行緒堆疊
STACK_SIZE, // 執行緒堆疊大小
&ThreadB_Handle, // 返回執行緒句柄
&ThreadB_Obj); // 執行緒信息結構體
cyg_thread_resume(ThreadA_Handle); // 啟動執行緒
cyg_thread_resume(ThreadB_Handle); // 啟動執行緒
return;
}