《FreeRTOS多任务之间的通信》(四种信号灯)

来源:互联网 发布:布尔玛和孙悟空 知乎 编辑:程序博客网 时间:2024/06/05 19:11


四种信号灯的介绍

1.计数信号灯:计数信号灯可以看成是长度大于 1 的队列

2.二值型信号灯:二进制信号灯可以认为长度是 1 的队列,二值型信号灯是种特殊的计数信号灯,二值信号灯和互斥锁十分相像,不过二值型信号灯适合用于同步。

3.互斥信号灯:互斥锁和二元信号量十分相像,不过两者间有细微的差别,互斥锁包含一个优先级继承机制,互斥锁适合用于互斥

4.递归互斥:这个我很少用,只对其API进行介绍

计数信号灯

API

创建一个计数信号量:xSemaphoreCreateCounting() 函数

xSemaphoreHandle xSemaphoreCreateCounting (unsigned portBASE_TYPE uxMaxCount, unsigned portBASE_TYPE uxInitialCount )uxMaxCount:可以达到的最大计数值。uxInitialCount:信号量创建时分配的初始值返回:已创建的信号量句柄,为xSemaphoreHandle 类型,如果信号量无法创建则为NULL

删除信号量void vSemaphoreDelete()

void vSemaphoreDelete( SemaphoreHandle_t xSemaphore )xSemaphore:信号量句柄
Demo

一个初始化函数,一个获取函数

static SemaphoreHandle_t xSemaphore_count_by = NULL;void count_semaphore_init(void *param){    /*信号量的计数最大值将为5,初始值为1*/    xSemaphore_count_by=xSemaphoreCreateCounting(5,1);    /*再来一个*/    xSemaphoreGive( xSemaphore_count_by );    if(xSemaphore_count_by == NULL)    {        /*创建互斥信号量失败,可以写自己的处理机制*/        printf("[%s]can't create  count_semaphore_init!\n",__func__);    }    vTaskDelete( NULL );}
void count_semaphore_demo(void *param){    for(;;)    {        /*判断这个互斥信号量是不是被创建*/        if(xSemaphore_count_by != NULL)        {            /*如果信号量无效,则最多等待10个系统节拍周期。*/              if( xSemaphoreTake( xSemaphore_count_by,(TickType_t)10) == pdTRUE )              {                               /*获取了信号量可以进行逻辑操作*/                 printf("[%s] Success!\n",__func__);                 /*释放互斥信号量*/                 #if 0                if(xSemaphoreGive( xSemaphore_count_by )==pdFALSE)                {                    /*错误处理*/                    printf("[%s]xSemaphoreGive error!\n",__func__);                }                #endif            }              else              {                  /*错误处理*/               printf("[%s] error!\n",__func__);            }          }        vTaskDelay(500);    }    vTaskDelete( NULL );}

main函数(只写了主要的函数)

if(xTaskCreate(count_semaphore_init, "count_semaphore_init", 512, NULL,2, NULL) != pdPASS){            printf("[%s] count_semaphore_init error\n",__func__);    }    if(xTaskCreate(count_semaphore_demo, "mutex_semaphore_demo", 512, NULL,1, NULL) != pdPASS){        printf("[%s] count_semaphore_demo error\n",__func__);    }
Log

可以在这里看到获取了两次信号量

[count_semaphore_demo] Success![count_semaphore_demo] Success![count_semaphore_demo] error![count_semaphore_demo] error!

二值型信号灯

对API的介绍

创建二值型信号量vSemaphoreCreateBinary()

void vSemaphoreCreateBinary( xSemaphoreHandle xSemaphore )xSemaphore :创建的二值型信号量

或者是下面的一种方式

xSemaphoreHandle  xSemaphoreCreateBinary()返回值:创建的二值型信号量

触发二值型信号量:xSemaphoreGive() (我在这里用的是触发这两个字我觉得这个比较合适)

xSemaphoreGive (xSemaphoreHandle xSemaphore )xSemaphore 即将释放的信号量的句柄,在信号量创建是返回返回值:如果信号量成功释放返回pdTRUE,如果发生错误则返回pdFALSE。

获取二值型信号量xSemaphoreTake()

xSemaphoreTake (xSemaphoreHandle xSemaphore, portTickType xBlockTime )xSemaphore,:将被获得的信号量句柄,此信号量必须已经被创建xBlockTime :等待信号量可用的时钟滴答次数返回值:如果成功获取信号量则返回pdTRUE, 超时则返回pdFALSE
Demo

构建三个任务,一个初始化的任务,一个发送信号的任务,一个进行接收的任务

static SemaphoreHandle_t xSemaphore_by = NULL;void semaphore_init(void *param){    /*初始化资源*/    xSemaphore_by=xSemaphoreCreateBinary();        if(xSemaphore_by == NULL)    {        /*创建二值信号量失败,可以写自己的处理机制    我这里做的打印*/        printf("[%s]can't create  xSemaphore!\n",__func__);    }    vTaskDelete( NULL );}void semaphore_send(void *param){     for(;;)    {        /*判断是否创建了这个二值信号量*/         if( xSemaphore_by != NULL )          {            /*做个延时这样可以方便从log看出结果*/             vTaskDelay(4000);            if(xSemaphoreGive( xSemaphore_by )==pdFALSE)            {                /*错误处理*/            }        }         vTaskDelay(500);    }     vTaskDelete( NULL );}void semaphore_achieve(void *param){    for(;;)    {         if( xSemaphore_by != NULL )          {              /*如果信号量无效,则最多等待10个系统节拍周期。*/              if( xSemaphoreTake( xSemaphore_by,(TickType_t)10) == pdTRUE )              {                             printf("[%s]achieve Success!\n",__func__);            }              else              {                  /*错误处理*/               printf("[%s]achieve error!\n",__func__);            }          }         vTaskDelay(100);    }    vTaskDelete( NULL );}

构建一个main函数:创建三个任务(这个是伪代码没有对内核启动等操作)

if(xTaskCreate(semaphore_init, "semaphore_init", 1024, NULL,2, NULL) != pdPASS){        printf("[%s] semaphore_init error\n",__func__);    }    if(xTaskCreate(semaphore_achieve, "semaphore_achieve", 1024,NULL,1, NULL) != pdPASS){            printf("[%s] semaphore_achieve error\n",__func__);    }    if(xTaskCreate(semaphore_send, "semaphore_send", 1024,NULL,1, NULL) != pdPASS){            printf("[%s] semaphore_send error\n",__func__);    }
log:(在这里只打印一部分log)
[semaphore_achieve]achieve error![semaphore_achieve]achieve error![semaphore_achieve]achieve error![semaphore_achieve]achieve error![semaphore_achieve]achieve Success!

互斥信号灯

API

xSemaphoreHandle xSemaphoreCreateMutex(void)

返回: 已创建的互斥锁信号量句柄,需要为xSemaphoreHandle类型

获取和释放信号量和上面的二值信号灯是一致的

Demo

构建两个任务,一个初始化任务,一个获取和释放的任务

static SemaphoreHandle_t xSemaphore_mutex_by = NULL;void mutex_semaphore_init(void *param){    xSemaphore_mutex_by=xSemaphoreCreateMutex();    if(xSemaphore_mutex_by == NULL)    {        /*创建互斥信号量失败,可以写自己的处理机制*/        printf("[%s]can't create  xSemaphore!\n",__func__);    }    vTaskDelete( NULL );}void mutex_semaphore_demo(void *param){    for(;;)    {        /*判断这个互斥信号量是不是被创建*/        if(xSemaphore_mutex_by != NULL)        {            /*如果信号量无效,则最多等待10个系统节拍周期。*/              if( xSemaphoreTake( xSemaphore_mutex_by,(TickType_t)10) == pdTRUE )              {                               /*获取了信号量可以进行逻辑操作*/                 printf("[%s] Success!\n",__func__);                 /*释放互斥信号量*/                if(xSemaphoreGive( xSemaphore_mutex_by )==pdFALSE)                {                    /*错误处理*/                    printf("[%s]xSemaphoreGive error!\n",__func__);                }            }              else              {                  /*错误处理*/               printf("[%s] error!\n",__func__);            }          }        vTaskDelay(500);    }    vTaskDelete( NULL );}

Mian函数:

int main(){    if(xTaskCreate(mutex_semaphore_init, "mutex_semaphore_init", 512, NULL,2, NULL) !=pdPASS)    {        printf("[%s] mutex_semaphore_init error\n",__func__);    }    if(xTaskCreate(mutex_semaphore_demo, "mutex_semaphore_demo", 512, NULL,1, NULL) != pdPASS)    {        printf("[%s] mutex_semaphore_demo error\n",__func__);    }    vTaskStartScheduler();    for(;;);}
log:(在这里只打印一部分log)
[mutex_semaphore_demo] Success![mutex_semaphore_demo] Success![mutex_semaphore_demo] Success![mutex_semaphore_demo] Success![mutex_semaphore_demo] Success![mutex_semaphore_demo] Success!

递归互斥

API

创建:

xSemaphoreHandle xSemaphoreCreateRecursiveMutex( void )返回: 已创建的互斥锁信号量为xSemaphoreHandle类型句柄

接收的释放和上面的三个不相同

接收:xSemaphoreTakeRecursive( xSemaphoreHandle xMutex, portTickType xBlockTime )参数: xMutex 将被获得的互斥锁句柄,此句柄由xSemaphoreCreateRecursiveMutex()返回xBlockTime 等待信号量可用的时钟滴答次返回值: 如果成功获取信号量则返回pdTRUE,如果xBlockTime超时而信号量还未可用则返回pdFALSE
释放:xSemaphoreGiveRecursive( xSemaphoreHandle xMutex )参数: xMutex: 将被释放的互斥锁的句柄,由 xSemaphoreCreateRecursiveMutex()返回返回值: 如果信号量成功释放则为pdTRUE
阅读全文
'); })();
1 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 怎么给宝宝煮饭 煮饭用什么水好 微波炉煮饭怎么煮 电饭锅煮饭不熟就跳 微波炉能煮饭吗 自来水可以煮饭吗 电饭锅不能煮饭 开水煮饭好吗 煮饭水放多少 微波炉怎样煮饭 用压力锅煮饭好吗 煮饭阿姨什么意思 用什么煮饭好吃 微波炉怎么煮饭 自来水煮饭可以吗 糙米怎么煮饭 煮饭怎么不粘锅 电饭煲煮饭放水 电饭锅煮饭煮不熟 煮饭下多少水 五谷杂粮煮饭 电压力锅煮饭要多长时间 电磁炉可以煮饭吗 怎样煮饭更营养 电饭煲煮饭不粘锅 怎么样煮饭不粘锅 电饭煲如何煮饭 电热锅可以煮饭吗 高压锅煮饭放多少水 高压锅可以煮饭吗 煮饭是什么意思 什么锅不能煮饭 电饭锅煮饭糊 电炒锅怎么煮饭 香肠煮饭怎么做 煮饭多少水合适 高压锅煮饭怎么煮 电饭煲煮饭要多少水 红豆怎么煮饭 煮饭阿姨职责 电饭锅怎么煮饭