AliOS-Things+STM32 (四) 同步机制(buf_queue)

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

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, 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值