小熊派BearPi-HM nano开发板 -- 内核篇: 4.互斥锁 5.信号量 6.消息队列

  • 模板说明

粤嵌鸿蒙 -- 学习笔记 ​

内核篇:(1 2 3篇线程 定时器 事件笔记在上一章)

​4.互斥锁

5.信号量

6.消息队列

  • 课前准备
    • 参考资料   ----  以下笔记中出现的代码可以在该网址的“四、BearPi-HM_Nano 案例开发”中查找
      • BearPi-HM_Nano: 小熊派BearPi-HM Nano开发板基于HarmonyOS的源码 (gitee.com)icon-default.png?t=M85Bhttps://gitee.com/bearpi/bearpi-hm_nano
      • 开发市场 (harmonyos.com)icon-default.png?t=M85Bhttps://repo.harmonyos.com/#/cn/solution/@bearpi%2Fbearpi_hm_nano   ----   小熊派开发板的源代码下载--涵盖例程
  • 听课记录
    • 4.mutex互斥锁  --  理解:拥有锁的任务独占资源,其他任务阻塞等待
      • 互斥锁的概念:
        • 1.互斥锁又称互斥型信号量,是一种特殊的二值信号量,用于实现对共享资源的独占式处理
        • 2.任意时刻互斥锁的状态只有两种:开锁闭锁
        • 3.当有任务持有时,互斥锁处于闭锁状态,这个任务获得该互斥锁的所有权
        • 4.当有任务释放时,该互斥锁被开锁,任务我失去该互斥锁的所有权
        • 5.当一个任务持有互斥锁时,其他任务将不能再对该互斥锁进行开锁或持有。
        • 6.多任务环境下往往存在许多任务竞争同一共享资源的应用场景,互斥锁可被用于对该共享资源的保护从而实现独占式访问
        • 另外,互斥锁可以解决信号量存在的优先级翻转问题。
      • osMutexNew    --   创建互斥锁

osMutexId_t osMutexNew(const osMutexAttr_t *attr)

        • 描述:

函数osMutexNew创建并初始化一个新的互斥锁对象,并返回指向互斥锁对象标识符的指针,如果出现错误则返回NULL,可以在RTOS启动(调用 osKernelStart)之前安全地调用该函数,但不能在内核初始化 (调用 osKernelInitialize)之前调用该函数。 注意 :不能在中断服务调用该函数

        • 参数:
          • attr:互斥对象属性,这里我通常填NULL
        • 代码设计:

小熊派BearPi-HM nano开发板 -- 内核篇: 4.互斥锁 5.信号量 6.消息队列_第1张图片

osMutexId_t mutex_id;             //定义全局变量 ​ ​mutex_id = osMutexNew(NULL);    //创建一个新的互斥锁,并返回指向互斥锁对象标识符的指针   if (mutex_id == NULL)                       //做一个简单的判断,是否创建互斥锁成功   {     printf("Falied to create Mutex!\n");   }

      • osMutexAcquire   --   获取互斥锁

osStatus_t osMutexAcquire(osMutexId_t mutex_id,uint32_t timeout)

        • 描述:

 函数osMutexAcquire一直等待,直到参数mutex_id指定的互斥对象可用为止。如果没有其他线程获得互斥锁,该函数立即返回并阻塞互斥锁对象。 注意 :不能在中断服务调用该函数

        • 参数:
          • mutex_id:通过osMutexNew获得互斥锁ID.(这里是mutex_id )
          • timeout:超时值.

osWaitForever   --    一直等待获取互斥锁

        • 代码设计:

// try to acquire mutex osMutexAcquire(mutex_id, osWaitForever);

      • osMutexRelease   --   释放互斥锁

osStatus_t osMutexRelease(osMutexId_t mutex_id)

        • 描述:

函数osMutexRelease释放一个由参数mutex_id指定的互斥量。当前等待这个互斥锁的其他线程将被置于就绪状态。 注意 :不能从中断服务例程调用此函数。

        • 参数:
          • mutex_id:通过osMutexNew获得互斥锁ID.(这里是mutex_id )
        • 代码设计:

 osMutexRelease(mutex_id);

      • osMutexDelete   --   删除互斥锁

osStatus_t osMutexDelete(osMutexId_t mutex_id)

        • 描述:

函数osMutexDelete 删除一个由参数mutex_id指定的互斥量。

        • 参数:
          • mutex_id:通过osMutexNew获得互斥锁ID.(这里是mutex_id )
        • 代码设计:

osMutexDelete(mid);

    • 5.semp信号量  --理解:互斥锁差不多
      • 信号量的概念:
        • 1.信号量(Semaphore)是一种实现任务间通信的机制,实现任务间同步或临界资源的互斥访问(4.互斥锁就属于信号量的一种)。常用于协助一组相互竞争的任务来访问临界资源。(这里的具体应用就是互斥锁)
        • 2.在多任务系统中,个任务之间需要同步或互斥实现临界资源的保护,信号量功能可以为用户提供这方面的支持。
        • 3.通常一个信号量的计数值用于对应有效的资源数,表示剩下的可被占用的互斥资源数。其值的含义分两种情况:
          • ①  0 ,表示没有积累下来的Post信号量操作,且有可能有在此信号量上阻塞的任务。
          • ② 正值 ,表示有一个或多个Post信号量操作。
        • 4.以同步为目的的信号量和以互斥为目的的信号量(互斥型看4.互斥锁)在使用有如下不同:
          • 用作互斥时:信号量创建后计数是满的,在需要使用临界资源时,先取信号量,使其变空,这样其他任务需要使用临界资源时就会因为无法取到信号量而阻塞,从而保证了临界资源的安全。--有信号量的独占资源
          • 用作同步时:信号量在创建后被置为空,任务1取到信号量而阻塞,任务2在魔种条件发生后,释放信号量,于是任务1得以进入READY或RUNNING,从而达到两个任务间同步。--相当于任务1就绪状态,等待任务2条件成立后任务1进行。
      • osSemaphoreNew   --   创建信号量  ==   理解:创建互斥锁

osSemaphoreId_t osSemaphoreNew(uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr)

        • 描述:

函数osMessageQueueNew创建并初始化一个消息队列对象。该函数返回消息队列对象标识符,如果出现错误则返回NULL,可以在RTOS启动(调用 osKernelStart)之前安全地调用该函数,也可以在内核初始化 (调用 osKernelInitialize)之前调用该函数。 注意 :不能在中断服务调用该函数

        • 参数:
          • max_count:可用令牌的最大数量.
          • initial_count:可用令牌的初始数量.
          • attr:信号量的属性;空:默认值.
        • 代码设计:

小熊派BearPi-HM nano开发板 -- 内核篇: 4.互斥锁 5.信号量 6.消息队列_第2张图片

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

      • osSemaphoreAcquire   --   获取(等待)信号量  ==  理解:获取互斥锁

osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id, uint32_t timeout)

        • 描述:

阻塞函数osSemaphoreAcquire一直等待,直到由参数semaphore_id指定的信号量对象的标记可用为止。如果一个令牌可用,该函数立即返回并递减令牌计数。 注意 :如果参数timeout设置为0,可以从中断服务例程调用。

        • 参数:
          • semaphore_id:由osSemaphoreNew获得的信号量ID.(这里是sem1 )
          • timeout:超时值.(这里我通常填osWaitForever--一直等待)
        • 代码设计:

//等待sem1信号量 osSemaphoreAcquire(sem1, osWaitForever);

      • osSemaphoreRelease   --   释放信号量  ==  理解:释放互斥锁

osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id)

        • 描述:

函数osSemaphoreRelease释放由参数semaphore_id指定的信号量对象的标记 注意 :该函数可以在中断服务例程调用

        • 参数:
          • semaphore_id:由osSemaphoreNew获得的信号量ID.
        • 代码设计:

osSemaphoreRelease(sem1);

      • osSemaphoreDelete   --   删除信号量  ==  理解:删除互斥锁

osStatus_t osSemaphoreDelete(osSemaphoreId_t semaphore_id)

        • 描述:

函数osSemaphoreDelete 删除由参数semaphore_id指定的信号量

        • 参数:
          • semaphore_id:由osSemaphoreNew获得的信号量ID.
        • 代码设计:

/删除信号量 osSemaphoreDelete(sem1);       ----->图片的s_data是申请的信号量ID,这里换成我们创建的信号量ID--->sem1

    • 6.message消息队列
      • 消息队列的概念:
        • 消息队列,是一种常用于任务间通信的数据结构,是西安了接收来自任务或中断的不固定长度的消息,病根选举不同的接口选择传递消息是否存放在自己空间.任务能够从队列里面读取消息,当队列中的消息是空时,挂起读取任务;当队列中有新消息时,挂起的读取任务被唤醒并处理新消息.
        • 用户在处理业务时,消息队列提供了异步处理机制,允许将一个消息放入队列,但并不立即处理它,同时队列还能起到缓冲消息作用.
        • LiteOS中使用队列数据结构实现任务异步通信工作,具体由如下特性:
          • 消息以先进先出方式排队,支持异步读写工作方式.
          • 读队列和写队列都支持超时机制.
          • 发送消息类型由通信双方约定,可以允许不同长度(不超过队列节点最大值)消息.
          • 一个任务能够从任意一个消息队列接收和发送消息.
          • 多个任务能够从同一个消息队列接收和发送消息.
          • 当队列使用结束后,如果时动态申请的内存,需要通过释放内存函数回收.
      • 消息队列运作原理:

小熊派BearPi-HM nano开发板 -- 内核篇: 4.互斥锁 5.信号量 6.消息队列_第3张图片

        • 创建队列时,根据用户传入队列长度和消息节点大学校来开辟i想要的内存空间以提供该队列使用,返回队列ID
        • 在队列控制块中维护一个消息头节点位置Head和一个消息为节点位置Tail来表示当前队列中消息存储情况.Head表示队列中被占用消息的位置.Tail表示队列中被空闲消息的起始位置.
        • 写队列时,根据Tail找到被占用消息节点末尾的空闲节点作为数据写入对象.
        • 读队列时,根据Head找到最先写入队列中的消息节点进行读取.
        • 删除队列时,根据传入的队列ID寻找到对应的队列,把队列状态置为未使用,释放原队列所占的空间,对应的队列控制头置为初始状态.
      • osMessageQueueNew   --   创建消息队列

osMessageQueueId_t osMessageQueueNew(uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr)

        • 描述:

函数osMessageQueueNew创建并初始化一个消息队列对象。该函数返回消息队列对象标识符,如果出现错误则返回NULL,可以在RTOS启动(调用 osKernelStart)之前安全地调用该函数,也可以在内核初始化 (调用 osKernelInitialize)之前调用该函数。 注意 :不能在中断服务调用该函数

        • 参数:
          • msg_count  :  队列中的最大消息数.
          • msg_size  :  最大消息大小(以字节为单位).
          • attr  :  消息队列属性;空:默认值.
        • 代码设计:

小熊派BearPi-HM nano开发板 -- 内核篇: 4.互斥锁 5.信号量 6.消息队列_第4张图片

osMessageQueueId_t mid_MsgQueue;     //number of Message Queue Objects #define MSGQUEUE_OBJECTS 16  mid_MsgQueue = osMessageQueueNew(MSGQUEUE_OBJECTS, 100, NULL);   if (mid_MsgQueue == NULL)   {     printf("Falied to create Message Queue!\n");   }

      • osMessageQueuePut   --   发送消息

osStatus_t osMessageQueuePut(osMessageQueueId_t mq_id,const void *msg_ptr,uint8_t msg_prio,uint32_t timeout)

        • 描述:

函数osMessageQueuePut将msg_ptr指向的消息放入参数mq_id指定的消息队列中。 注意 :如果参数timeout设置为0,可以从中断服务例程调用

        • 参数:
          • mq_id:   由osMessageQueueNew获得的消息队列ID.
          • msg_ptr:   要发送的消息.
          • msg_prio:   指优先级.
          • timeout:   超时值.
        • 代码设计:

小熊派BearPi-HM nano开发板 -- 内核篇: 4.互斥锁 5.信号量 6.消息队列_第5张图片

小熊派BearPi-HM nano开发板 -- 内核篇: 4.互斥锁 5.信号量 6.消息队列_第6张图片

typedef struct {   //object data type   char *Buf;   uint8_t Idx; } MSGQUEUE_OBJ_t; MSGQUEUE_OBJ_t msg;  void Thread_MsgQueue1(void *argument)    //发送消息线程 {   (void)argument;   //do some work...   msg.Buf = "Hello BearPi-HM_Nano!";   msg.Idx = 0U;   while (1)   {     osMessageQueuePut(mid_MsgQueue, &msg, 0U, 0U);     //suspend thread     osThreadYield();     osDelay(100);   } } ​

      • osMessageQueueGet   --   获取消息

osStatus_t osMessageQueueGet(osMessageQueueId_t mq_id,void *msg_ptr,uint8_t *msg_prio,uint32_t   timeout)

        • 描述:

函数osMessageQueueGet从参数mq_id指定的消息队列中检索消息,并将其保存到参数msg_ptr所指向的缓冲区中。 注意 :如果参数timeout设置为0,可以从中断服务例程调用。

        • 参数:
          • mq_id:   由osMessageQueueNew获得的消息队列ID.
          • msg_ptr:   要发送的消息.
          • msg_prio:   指优先级.
          • timeout:   超时值.
        • 代码设计:

小熊派BearPi-HM nano开发板 -- 内核篇: 4.互斥锁 5.信号量 6.消息队列_第7张图片

void Thread_MsgQueue2(void *argument) {   (void)argument;   osStatus_t status;   while (1)   {     //Insert thread code here...     //wait for message     status = osMessageQueueGet(mid_MsgQueue, &msg, NULL, 0U);     if (status == osOK)     {       printf("Message Queue Get msg:%s\n", msg.Buf);     }   } }

      • osMessageQueueDelete   --   删除消息队列

osStatus_t osMessageQueueDelete(osMessageQueueId_t mq_id)

        • 描述:

函数osMessageQueueDelete   删除mq_id指定的消息队列对象

        • 参数:
          • mq_id: 由osMessageQueueNew获得的消息队列ID.
        • 代码设计:

osMessageQueueDelete (mid_MsgQueue )       //图片qid以创建获得的消息队列ID为主

你可能感兴趣的:(小熊派BearPi-HM,nano开发板,小熊派BearPi-HM,nano,harmonyos,华为)