Alios中的buf_queue,相当于Freertos中的msg queue,是一种很常用的消息同步机制。一般用法是在一个handler loop里,阻塞地receive其他线程send过来的msg,根据msg的参数做统一的消息处理。我们先看下这次主要分析的接口:
/**
* This function will create a dyn-queue
* @param[out] queue pointer to the queue(The space is provided by kernel)
* @param[in] name pointer to the nam
* @param[in] size size of the buf
* @param[in] max_msg max size of one msg
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_buf_queue_dyn_create(kbuf_queue_t **queue, const name_t *name,
size_t size, size_t max_msg);
/**
* This function will delete a dyn-queue
* @param[in] queue pointer to the queue
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_buf_queue_dyn_del(kbuf_queue_t *queue);
/**
* This function will send a msg at the end of queue
* @param[in] queue pointer to the queue
* @param[in] msg pointer to msg to be send
* @param[in] size size of the msg
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_buf_queue_send(kbuf_queue_t *queue, void *msg, size_t size);
/**
* This function will receive msg form aqueue
* @param[in] queue pointer to the queue
* @param[in] ticks ticks to wait before receiving msg
* @param[out] msg pointer to the buf to save msg
* @param[out] size size of received msg
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_buf_queue_recv(kbuf_queue_t *queue, tick_t ticks, void *msg, size_t *size);
由于为了讲清楚buf_queue需要的内存分配,所以分析动态分配的buf_queue,这样用户不需要对kbuf_queue_t结构做任何处理,直接使用。
先了解一下kbuf_queue_t结构:
typedef struct {
blk_obj_t blk_obj; //*blk对象,和上一章的mutex一样,记录task调用mutex如果被阻塞住时的一些信息记录*/
void *buf; //需要缓冲消息队列的存放地址
k_ringbuf_t ringbuf; //环形buf结构体,记录ringbuf内各个对象,当ringbuf宏申请为RINGBUF_TYPE_DYN比较有意义
size_t max_msg_size; //每条消息允许的最大长度
size_t cur_num; //当前buf里有存有多少消息
size_t peak_num; //buf里存在过的最大消息数量
size_t min_free_buf_size; //buf存在过的最小剩余空间大小
#if (RHINO_CONFIG_KOBJ_LIST > 0)
klist_t buf_queue_item; //用来插入到g_kobj_list里,便于查询管理
#endif
#if (RHINO_CONFIG_USER_SPACE > 0)
uint32_t key;
#endif
uint8_t mm_alloc_flag; //buf的申请方式,动态分配或是用户静态分配
} kbuf_queue_t;
typedef struct {
//环形buf结构体内各个对象
uint8_t *buf; //环形buf的起始位置,不会随着msg的进出改变
uint8_t *end; //环形buf的结束位置,不会随着msg的进出改变
uint8_t *head; //环形buf的当前最早进入的一个消息的起始位置,会随着msg的进出改变
uint8_t *tail; //环形buf的当前最晚进入的消息的结束位置,也是最新将要插入消息的开始位置,会随着msg的进出改变
size_t freesize; //环形buf当前的剩余空间
size_t type; //环形buf使用方式:RINGBUF_TYPE_FIX:每个消息定长,RINGBUF_TYPE_DYN:每个消息长度可以自定义
size_t blk_size; //针对RINGBUF_TYPE_FIX类型有效,记录每个消息的长度
} k_ringbuf_t;
由于RINGBUF_TYPE_FIX类型的定长消息处理相对较容易,所以我们主要研究RINGBUF_TYPE_DYN类型的不定长消息。其实看完上边的注释,buf_queue的大概使用规则应该就清楚了,接下来我们来看下具体的buf_queue的实现原理:
kstat_t krhino_buf_queue_dyn_create(kbuf_queue_t **queue, const name_t *name,
size_t size, size_t max_msg)
{
//申请RINGBUF_TYPE_DYN类型的buf_queue, 其中size为buf缓冲区的长度,max_msg为单个msg规定的最大允许长度。
return buf_queue_dyn_create(queue, name, size, max_msg, RINGBUF_TYPE_DYN);
}
static kstat_t buf_queue_dyn_create(kbuf_queue_t **queue, const name_t *name,
size_t size, size_t max_msg, uint8_t type)
{
kstat_t stat;
kbuf_queue_t *queue_obj;
NULL_PARA_CHK(queue);
if (size == 0u) {
return RHINO_BUF_QUEUE_SIZE_ZERO;
}
//动态申请kbuf_queue_t结构体
queue_obj = krhino_mm_alloc(sizeof(kbuf_queue_t));
if (queue_obj == NULL) {
return RHINO_NO_MEM;
}
//动态申请buf size的内存
queue_obj->buf = krhino_mm_alloc(size);
if (queue_obj->buf == NULL) {
krhino_mm_free(queue_obj);
return RHINO_NO_MEM;
}
//创建buf queue
stat = buf_queue_create(queue_obj, name, queue_obj->buf, size, max_msg,
K_OBJ_DYN_ALLOC, RINGBUF_TYPE_DYN);
if (stat != RHINO_SUCCESS) {
krhino_mm_free(queue_obj->buf);
krhino_mm_free(queue_obj);
return stat;
}
*queue = queue_obj;
return RHINO_SUCCESS;
}
static kstat_t buf_queue_create(kbuf_queue_t *queue,

本文深入解析了Alios中的buf_queue机制,一种类似于Freertos的msgqueue,用于线程间消息同步。详细介绍了kbuf_queue_t结构,包括其内部的环形缓冲区管理,并分析了关键接口如创建、发送、接收和删除buf_queue的实现原理。
最低0.47元/天 解锁文章
1473

被折叠的 条评论
为什么被折叠?



