RT-Thread信號量的基本操作

抽象的來講,信號量的特性如下:信號量是一個非負整數(車位數),所有通過它的線程/進程(車輛)都會將該整數減一(通過它當然是爲了使用資源),當該整數值爲 0 時,所有試圖通過它的線程都將處於等待狀態。在信號量上我們定義兩種操作: take ( 獲取) 和Release(釋放)。當一個線程調用 take 操作時,它要麼得到資源然後將信號量減一,要麼
一直等下去(指放入阻塞隊列),直到信號量大於等於一時。 Release(釋放)實際上是在信號量上執行加操作, take(獲取)實際上是在信號量上執行減操作。RT-Thread 中的信號量有靜態和動態之分(同靜態線程、動態線程), 和信號量有關的操作如下:
  初始化—rt_sem_init()( 對應靜態信號量) ;
  建立—rt_sem_create()( 對應動態信號量);
  獲取—rt_sem_take();
  釋放—rt_sem_release();
  脫離—rt_sem_detach()( 對應靜態信號量) ;
  刪除—rt_sem_delete()( 對應動態信號量) ;

複製代碼
/**********************************************************************************************************
*
*    模塊名稱 : 功能演示
*    文件名稱 : test.c
*    版    本 : V1.0
*    說    明 :
*    修改記錄 :
*        版本號  日期        作者                        說明
*
*        v1.0    2013-4-20   jiezhi320(UP MCU 工作室)    演示信號量的基本操作 源碼來自官方教程文件
*
*    Copyright (C), 2012-2013,
*   淘寶店:   http://shop73275611.taobao.com
*   QQ交流羣: 258043068
*
**********************************************************************************************************/
#include <rtthread.h>
#include <stm32f10x.h>
#include "test.h"

rt_uint32_t  g_tmp;/* 定義一個全局變量*/

/*  變量分配4字節對齊 */
ALIGN(RT_ALIGN_SIZE)

/*  靜態線程的 線程堆棧*/
static rt_uint8_t thread1_stack[512];

/* 靜態線程的 線程控制塊 */
static struct rt_thread thread_test1;

static void test1_thread_entry(void* parameter);


/* 信號量控制塊 */
static struct rt_semaphore static_sem;
/* 指向信號量的指針 */
static rt_sem_t dynamic_sem = RT_NULL;

rt_err_t demo_thread_creat(void)
{
    rt_err_t result;

    /* 初始化靜態信號量,初始值是0 */
    result = rt_sem_init(&static_sem, "ssem", 0, RT_IPC_FLAG_FIFO);
    if (result != RT_EOK)
    {
        rt_kprintf("init static semaphore failed.\n");
        return -1;
    }

    /* 創建一個動態信號量,初始值是0 */
    dynamic_sem = rt_sem_create("dsem", 0, RT_IPC_FLAG_FIFO);
    if (dynamic_sem == RT_NULL)
    {
        rt_kprintf("create dynamic semaphore failed.\n");
        return -1;
    }

    /* 創建靜態線程 : 優先級 16 ,時間片 5個系統滴答 */
    result = rt_thread_init(&thread_test1,
                            "test1",
                            test1_thread_entry, RT_NULL,
                            (rt_uint8_t*)&thread1_stack[0], sizeof(thread1_stack), 16, 5);

    if (result == RT_EOK)
    {
        rt_thread_startup(&thread_test1);
    }
    return 0;
}

void test1_thread_entry(void* parameter)
{
    rt_err_t result;
    rt_tick_t tick;

    /* 1. staic semaphore demo */
    /* 獲得當前的OS Tick */
    tick = rt_tick_get();

    /* 試圖持有信號量,最大等待10個OS Tick後返回 */
    result = rt_sem_take(&static_sem, 10);  //獲取
    if (result == -RT_ETIMEOUT)
    {
        /* 超時後判斷是否剛好是10個OS Tick */
        if (rt_tick_get() - tick != 10)
        {
            rt_sem_detach(&static_sem);     //脫離—rt_sem_detach()( 對應靜態信號量) ;
            return ;
        }
        rt_kprintf("take semaphore timeout\n");  //////////////////////////////////////
    }
    else
    {
        /* 因爲沒有其他地方釋放信號量,所以不應該成功持有信號量,否則測試失敗 */
        rt_kprintf("take a static semaphore, failed.\n");
        rt_sem_detach(&static_sem);     //脫離—rt_sem_detach()( 對應靜態信號量) ;     
        return ;
    }

    /* 釋放一次信號量 */
    rt_sem_release(&static_sem);    //釋放—rt_sem_release();

    /* 永久等待方式持有信號量 */
    result = rt_sem_take(&static_sem, RT_WAITING_FOREVER);//獲取—rt_sem_take();
    if (result != RT_EOK)
    {
        /* 不成功則測試失敗 */
        rt_kprintf("take a static semaphore, failed.\n");
        rt_sem_detach(&static_sem);//脫離—rt_sem_detach()( 對應靜態信號量) ;
        return ;
    }

    rt_kprintf("take a staic semaphore, done.\n");////////////////////////////////////////

    /* 脫離信號量對象 */
    rt_sem_detach(&static_sem);//脫離—rt_sem_detach()( 對應靜態信號量) ;

    /* 2. dynamic semaphore test */

    tick = rt_tick_get();

    /* 試圖持有信號量,最大等待10個OS Tick後返回 */
    result = rt_sem_take(dynamic_sem, 10);
    if (result == -RT_ETIMEOUT)
    {
        /* 超時後判斷是否剛好是10個OS Tick */
        if (rt_tick_get() - tick != 10)
        {
            rt_sem_delete(dynamic_sem);
            return ;
        }
        rt_kprintf("take semaphore timeout\n");/////////////////////////////////////////////////////
    }
    else
    {
        /* 因爲沒有其他地方釋放信號量,所以不應該成功持有信號量,否則測試失敗 */
        rt_kprintf("take a dynamic semaphore, failed.\n");
        rt_sem_delete(dynamic_sem);
        return ;
    }

    /* 釋放一次信號量 */
    rt_sem_release(dynamic_sem);

    /* 永久等待方式持有信號量 */
    result = rt_sem_take(dynamic_sem, RT_WAITING_FOREVER);
    if (result != RT_EOK)
    {
        /* 不成功則測試失敗 */
        rt_kprintf("take a dynamic semaphore, failed.\n");
        rt_sem_delete(dynamic_sem);
        return ;
    }

    rt_kprintf("take a dynamic semaphore, done.\n");///////////////////////////////////////////
    /* 刪除信號量對象 */
    rt_sem_delete(dynamic_sem);
}
複製代碼

 

演示了靜態、動態信號量的各種操作。例程的運行輸出如下:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章