请选择 进入手机版 | 继续访问电脑版
查看: 794|回复: 0

[技术交流] ALIOS之消息队列

[复制链接]

74

主题

169

帖子

573

积分

利尔达员工

Rank: 9Rank: 9Rank: 9

积分
573
发表于 2020-11-2 09:52:13 | 显示全部楼层 |阅读模式
  1、前言

  在多任务系统中,任务间互相同步等待共享资源,我们一般会使用信号量,如果需要互斥,则使用互斥量。而任务间互相收发消息则可以使用消息队列。消息队列使用类似信号量的机制进行任务间的同步,并使用环形缓冲池来进行消息的队列缓冲管理,以达到任务间收发消息的阻塞和通知管理。

  实现消息队列的目的在于任务间互相收发消息。

  2、消息队列的创建与删除
  (1)静态创建:kstat_t  krhino_queue_create(kqueue_t  *queue,  const name_t  *name,  void  *   *start,  size_t  msg_num)
  (2)动态创建:kstat_t  krhino_queue_dyn_create(kqueue_t  *   *queue,  const name_t  *name,  size_t  msg_num)

  queue的创建主要是建立三种数据结构:queue的阻塞队列blk_obj,用于管理等待该队列的任务列表;queue的消息管理msg_q结构,用来管理当前消息队列数量;queue的环形缓冲池ringbuf,用来缓存消息的队列指针。

  动态接口和静态接口的差异在于,krhino_queue_dyn_create在函数内部动态申请了queue以及ring buffer需要的内存。

  (3)静态删除:kstat_t  krhino_queue_del(kqueue_t  *queue)
  (4)动态删除:kstat_t  krhino_queue_dyn_del(kqueue_t  *queue)

  动态删除需要释放queue的ring buffer队列queue -> ringbuf,以及queue本身内存。

  3、消息队列的发送和接收


  消息队列从消息发送的通道上来说分为两种,消息往ring buffer发送以及消息直接往任务发送并唤醒任务接收。当queue中没有任务阻塞,即没有任务在等待接收消息时,此消息会放入ring buffer进行缓存;当queue中有任务在等待接收数据时,则消息不再往ring buffer缓存,而是直接唤醒阻塞任务,并将消息直接送给任务的消息数据结构task->msg。

  其处理流程如所示附件所示:

  消息队列的接收和发送相对应,其函数原型为:kstat_t  krhino_queue_recv(kqueue_t  *queue,  tick_t  ticks,  void  **msg),其处理流程如下所示:

  (1)先判断ring buffer中有无缓冲队列需要处理,如果有则从ring buffer的head处取出一个消息指针msg。
  (2)如果当前缓冲区没有消息缓存,则当前任务需要等待,此时处理类似信号量的任务等待,会通过krhino_queue_recv传入的延时参数ticks来进行非等待、永久等待和延时等待的处理。永久等待和延时等待会将任务加入queue的阻塞队列,延时等待还会加入tick的处理队列,以便超时唤醒。
  (3)当阻塞任务被唤醒时,需要判断是否被唤醒成功,如果是则获取task->msg作为获取的消息队列,如果是被超时等恢复,则返回失败。

  4、消息队列维测信息获取



  queue模块提供了三个维测接口来获取和维护queue信息:

  kstat_t  krhino_queue_is_full(kqueue_t  *queue)
  该接口通过消息队列中ring buffer的缓存数目,来判断缓存区是否已满。如果缓冲队列已满,后续的queue_send会失败。

  kstat_t  krhino_queue_info_get(kqueue_t  *queue, msg_info_t  * info)
  该接口调用会返回queue内部的基础信息,包括缓冲队列起始地址,目前数目、总大小等。

  kstat_t  krhino_queue_flush(kqueue_t  *queue)
  该接口用于将queue内的ring buffer缓冲清除,并将缓冲数目清0。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表