您当前的位置: 首页 >  HarmonyOS

仙剑情缘

暂无认证

  • 2浏览

    0关注

    333博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Bearpi开发板之HarmonyOS信号量

仙剑情缘 发布时间:2022-05-01 21:36:18 ,浏览量:2

信号量的概念
  1. 信号量(Semaphore)是一种实现任务间通信的机制,实现任务之间同步或临界资源的互斥访问。常用于协助一组相互竞争的任务来访问临界资源。

  2. 在多任务系统中,各个任务之间需要同步或互斥实现临界资源的保护,信号量功能可以为用户提供这方面的支持。

  3. 通常一个信号量的计数值用于对应有效的资源数,表示剩下的可被占用的互斥资源数。其值的含义分两种情况: 1)0,表示没有积累下来的Post信号量操作,且有可能有在此信号量上阻塞的任务。 2)正值,表示有一个或多个Post信号量操作。

  4. 以同步为目的的信号量和以互斥为目的的信号量在使用有如下不同: 1)用作互斥时,信号量创建后记数是满的,在需要使用临界资源时,先取信号量,使其变空,这样其他任务需要使用 临界资源时就会因为无法取到信号量而阻塞,从而保证了临界资源的安全。 2)用作同步时,信号量在创建后被置为空,任务1取信号量而阻塞,任务2在某种条件发生后,释放信号量,于是任务 1得以进入READY或RUNNING态,从而达到了两个任务间的同步。

运作原理

1、信号量初始化,为配置的N个信号量申请内存(N值可以由用户自行配置,受内存限制),并把所有的信号量初始化成未使用,并加入到未使用链表中供系统使用。 2、信号量创建,从未使用的信号量链表中获取一个信号量资源,并设定初值。 3、信号量申请,若其计数器值大于0,则直接减1返回成功。否则任务阻塞,等待其它任务释放该信号量,等待的超时时间可设定。当任务被一个信号量阻塞时,将该任务挂到信号量等待任务队列的队尾。 4、信号量释放,若没有任务等待该信号量,则直接将计数器加1返回。否则唤醒该信号量等待任务队列上的第一个任务。 5、信号量删除,将正在使用的信号量置为未使用信号量,并挂回到未使用链表。 6、信号量允许多个任务在同一时刻访问同一资源,但会限制同一时刻访问此资源的最大任务数目。访问同一资源的任务数达到该资源的最大数量时,会阻塞其他试图获取该资源的任务,直到有任务释放该信号量。

cmsis_os2的API信号量接口简介
  1. 创建互斥锁:osSemaphoreId_t osSemaphoreNew (uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr);
  2. 获取互斥锁:osStatus_t osSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout);
  3. 释放互斥锁:osStatus_t osSemaphoreRelease (osSemaphoreId_t semaphore_id);
  4. 删除互斥锁:osStatus_t osMutexDelete (osMutexId_t mutex_id);
创建3个任务和一个容量为4的信号量
#include 
#include 
#include "ohos_init.h"
#include 
#include "cmsis_os2.h"
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"




void thread1(void *p)
{
   
  while(1)
  {
       //申请两次信号量,使得thread2和thread3能同步执行
        osSemaphoreRelease(p); 
        osSemaphoreRelease(p);
       
        printf("thread1 Release  Semap\n");
        osDelay(100);
       
  }
}

void thread2(void *p)
{
  
  while(1)
  {
    osSemaphoreAcquire(p,osWaitForever);
    
    printf("thread2 get Semap\n");
    osDelay(1);
  }
}


void thread3(void *p)
{
 
  while(1)
  {
    osSemaphoreAcquire(p,osWaitForever);
     
    printf("thread3 get Semap\n");
    osDelay(1);
  }
}



void my_led_example(void)
{
    GpioInit();
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_2,WIFI_IOT_IO_FUNC_GPIO_2_GPIO);
    GpioSetDir(WIFI_IOT_IO_NAME_GPIO_2,WIFI_IOT_GPIO_DIR_OUT);
    
    osThreadAttr_t attr;
    attr.attr_bits = 0;
    attr.cb_mem = NULL;
    attr.cb_size = 0;
    attr.stack_mem = NULL;
    attr.stack_size = 1024;
    attr.priority = 25;

    static osSemaphoreId_t sem;
    sem = osSemaphoreNew(4,0,NULL);
    if (sem == NULL)
    {
        printf("Falied to create Semaphore!\n");
    }

   osThreadId_t id = osThreadNew(thread1,sem,&attr);
   if(id == NULL)
   {
        printf("Falied to create thread1!\n");
   }
    
   
    id = osThreadNew(thread2,sem,&attr);
   if(id == NULL)
   {
        printf("Falied to create thread2!\n");
   }

   id = osThreadNew(thread3,sem,&attr);
   if(id == NULL)
   {
        printf("Falied to create thread3!\n");
   }

 
  
}
SYS_RUN(my_led_example);
  • 编译烧录运行

在这里插入图片描述

扩展实验代码
#include 
#include 
#include "ohos_init.h"
#include 
#include "cmsis_os2.h"
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"




void thread1(void *p)
{
   osStatus_t status;
  while(1)
  {
       //申请两次信号量,使得thread2和thread3能同步执行
       status = osSemaphoreRelease(p); 
      
        if(status != osOK)
        {
         printf("Thread1 Release Semap failed\n");
        }
        else
        {
          printf("Thread1 Release Semap success\n");
        }

        osDelay(100);
       
  }
}

void thread2(void *p)
{
  osStatus_t status;
  while(1)
  {
    status = osSemaphoreAcquire(p,osWaitForever);
    
    if(status != osOK)
    {
      printf("thread2 get Semap failed\n");
    }
    else
    {
       printf("thread2 get Semap success\n");
    }
    osDelay(1);
   
  }
}


void thread3(void *p)
{
  osStatus_t status;
  while(1)
  {
     status = osSemaphoreAcquire(p,osWaitForever);
     
     if(status != osOK)
    {
      printf("thread3 get Semap failed\n");
    }
    else
    {
       printf("thread3 get Semap success\n");
    }
    osDelay(1);
  }
}



void my_led_example(void)
{
    GpioInit();
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_2,WIFI_IOT_IO_FUNC_GPIO_2_GPIO);
    GpioSetDir(WIFI_IOT_IO_NAME_GPIO_2,WIFI_IOT_GPIO_DIR_OUT);
    
    osThreadAttr_t attr;
    attr.attr_bits = 0;
    attr.cb_mem = NULL;
    attr.cb_size = 0;
    attr.stack_mem = NULL;
    attr.stack_size = 1024;
    attr.priority = 25;

    static osSemaphoreId_t sem;
    sem = osSemaphoreNew(4,0,NULL);
    if (sem == NULL)
    {
        printf("Falied to create Semaphore!\n");
    }

   osThreadId_t id = osThreadNew(thread1,sem,&attr);
   if(id == NULL)
   {
        printf("Falied to create thread1!\n");
   }
    
   
    id = osThreadNew(thread2,sem,&attr);
   if(id == NULL)
   {
        printf("Falied to create thread2!\n");
   }

   id = osThreadNew(thread3,sem,&attr);
   if(id == NULL)
   {
        printf("Falied to create thread3!\n");
   }

 
  
}
SYS_RUN(my_led_example);
  • 编译烧录运行

在这里插入图片描述

信号量互斥演示代码
#include 
#include 
#include "ohos_init.h"
#include 
#include "cmsis_os2.h"
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"




void thread1(void *p)
{
   osStatus_t status;
  while(1)
  {
    printf("thread1 is running\n");
    status = osSemaphoreAcquire(p,osWaitForever);
    
    if(status != osOK)
    {
      printf("thread1 get Semap failed\n");
    }
    else
    {
       printf("thread1 get Semap success\n");
       printf("thread1 delay 1s\n");
       osDelay(100);
       status = osSemaphoreRelease(p); 
    }
   
    printf("thread1 is exiting\n");
    osDelay(150);

  }
}

void thread2(void *p)
{
  osStatus_t status;
  while(1)
  {
    printf("thread2 is running\n");
    status = osSemaphoreAcquire(p,50);
    
    if(status != osOK)
    {
      printf("thread2 get Semap failed\n");
    }
    else
    {
       printf("thread2 get Semap success\n");
       status = osSemaphoreRelease(p); 
    }
     
   
   
     printf("thread2 is exiting\n");
    osDelay(50);
  }
}




void my_led_example(void)
{
    GpioInit();
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_2,WIFI_IOT_IO_FUNC_GPIO_2_GPIO);
    GpioSetDir(WIFI_IOT_IO_NAME_GPIO_2,WIFI_IOT_GPIO_DIR_OUT);
    
    osThreadAttr_t attr;
    attr.attr_bits = 0;
    attr.cb_mem = NULL;
    attr.cb_size = 0;
    attr.stack_mem = NULL;
    attr.stack_size = 1024;
    attr.priority = 25;

    static osSemaphoreId_t sem;
    sem = osSemaphoreNew(1,1,NULL);
    if (sem == NULL)
    {
        printf("Falied to create Semaphore!\n");
    }

   osThreadId_t id = osThreadNew(thread1,sem,&attr);
   if(id == NULL)
   {
        printf("Falied to create thread1!\n");
   }
    
    attr.priority = 26;
    id = osThreadNew(thread2,sem,&attr);
   if(id == NULL)
   {
        printf("Falied to create thread2!\n");
   }

   

 
  
}
SYS_RUN(my_led_example);
  • 编译烧录运行 在这里插入图片描述
  • 演示信号量互斥分析 在这里插入图片描述
关注
打赏
1658017818
查看更多评论
立即登录/注册

微信扫码登录

1.0313s