os_msgq_recv
所属模块:通信机制 | 类型:消息队列接收函数
函数简介
os_msgq_recv 用于从消息队列中读取数据,
支持阻塞与非阻塞两种模式。
当队列为空时任务可进入等待状态;
当队列有数据时直接读取并触发发送端唤醒。
函数原型
char os_msgq_recv(os_msgq_t *q, u8 obj, u8 *_data, char nonblock);
参数说明
| 参数 |
说明 |
| q |
消息队列控制块指针 |
| obj |
资源ID(用于唤醒等待发送任务) |
| _data |
接收数据存储地址 |
| nonblock |
非阻塞标志(1=不阻塞 / 0=阻塞) |
返回值
1 - 成功接收数据
0 - 非阻塞模式下未就绪或被唤醒返回
-1 - 等待失败或异常
源码实现
/*------------------------------------------------------------------------
| FILE DESCRIPTION |
------------------------------------------------------------------------*/
/*------------------------------------------------------------------------
| - File name : msgq_recv.c
| - Author : 谭舒
| - Update date : 2026-09-19
| - Copyright(C) : 2026 HRTOS. All rights reserved.
------------------------------------------------------------------------*/
/*------------------------------------------------------------------------
| INCLUDES |
------------------------------------------------------------------------*/
#include "hrtos_internal.h"
/*------------------------------------------------------------------------
| API FUNCTIONS |
------------------------------------------------------------------------*/
/**
* @brief 从消息队列接收一个消息。
*
* @param[in] q 消息队列控制块指针。
* @param[in] obj 资源对象编号。
* @param[out] _data 接收数据存储地址。
* @param[in] nonblock 非阻塞模式标志。
*
* @return 操作结果。
* @retval 1 消息接收成功。
* @retval 0 非阻塞模式下队列为空。
* @retval 其他 等待操作返回的结果。
*
* @note 当消息队列非空时,直接读取队头消息并更新队列状态。
* 当消息队列为空时,非阻塞模式直接返回,
* 阻塞模式下当前任务进入消息接收等待状态。
* 消息读取后,当存在等待发送任务时唤醒对应任务。
*/
char os_msgq_recv(os_msgq_t *q, u8 obj, u8 *_data, char nonblock)
{
u8 i;
EA = 0;
/* -------------------------
* 1. 队列为空
* 当前任务进入等待状态
* ------------------------- */
if(q->count == 0)
{
EA = 1;
/* 非阻塞模式直接返回 */
if(nonblock)
{
return 0;
}
/* 队列空 */
i = os_wait(WAIT_MSG_RECV, obj, 0);
}
/* -------------------------
* 2. 队列非空,直接读取消息
* ------------------------- */
if(q->count > 0)
{
*_data = q->buf[q->tail]; //读取队头消息
q->tail = (q->tail + 1) % q->_size;//更新读指针
q->count--; //消息数量减1
/* -------------------------
* 队列释放出空闲空间
* 唤醒等待发送的任务
* ------------------------- */
if(OS_RES[obj].wait_mask)
{
u8 next = OS_INVALID_ID;
u8 i;
for(i = 0; i < OS_MAX_TASK; i++)
{
if((OS_RES[obj].wait_mask & ((u16)1 << i)) &&
(OS_TASK[i].wait_type == WAIT_MSG_SEND))
{
next = i;
break;
}
}
if(next != OS_INVALID_ID)
{
wake_task(next, WAIT_SIGNAL);
}
}
EA = 1;
return 1;
}
EA = 1;
/* 队列空 */
return i;
}
/*------------------------------------------------------------------------
| END OF FILE: msgq_recv.c |
------------------------------------------------------------------------*/
使用示例
void recv_task()
{
u8 data;
if(os_msgq_recv(&q, 0, &data, 0))
{
// 处理数据
}
}
注意事项
该函数是典型生产者-消费者模型实现,
在队列为空时可能进入阻塞状态,由调度器唤醒。