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。
|