全部文档
OneOS简介 硬件支持 编译构造工具 API参考文档 高级语言 用户编程手册 应用笔记 FAQ

数据队列


简介

数据队列是另外一种任务间的通信机制,在发送数据时,需要指定数据的地址和大小。它能够完成邮箱和消息队列所能够实现的功能,但又有一些差异性。具体差异如下:

(1)邮箱在发送数据时,发送固定大小的数据(4byte);而数据队列传送的是固定大小的数据项(即struct os_data_item,该数据项包含数据地址和大小);

(2)消息队列初始化时,指定了每条消息的最大长度,发送消息时复制该消息内容到消息队列预先分配好的缓冲区中,即消息队列传送的是具体消息内容,而数据队列传送的是固定大小的数据项;

(3)数据队列增加了一个通知回调函数;

(4)数据队列增加了一个接口,可以读取但保留数据队列中的数据;

(5)数据队列增加了一个门限值,决定在何种情况下读取数据时唤醒被阻塞的任务。


重要定义及数据结构

宏定义

#define OS_DATAQUEUE_EVENT_UNKNOWN     0x00
#define OS_DATAQUEUE_EVENT_POP         0x01
#define OS_DATAQUEUE_EVENT_PUSH        0x02
#define OS_DATAQUEUE_EVENT_THRESHOLD   0x03
定义 说明
OS_DATAQUEUE_EVENT_UNKNOWN 未知的事件
OS_DATAQUEUE_EVENT_POP POP数据时,若剩余的数据项个数大于门限值,则调用通知回调函数并通知该事件
OS_DATAQUEUE_EVENT_PUSH PUSH数据时,若没有POP任务阻塞,则会调用通知回调函数并通知该事件;否则唤醒被阻塞的POP任务
OS_DATAQUEUE_EVENT_THRESHOLD POP数据时,若剩余的数据项个数小于等于门限值,则调用通知回调函数并通知该事件

结构体

struct os_data_item
{
    const void *data_ptr;
    os_size_t  data_size;
};
struct os_data_item参数 说明
data_ptr 发送数据的地址
data_size 发送数据的大小
struct os_data_queue
{
    os_uint16_t size;                       /* Data queue holds the maximum number of data item. */
    os_uint16_t threshold;                  /* When the number of data item less than this,resume the push task. */

    os_uint16_t get_index;                  /* get index */
    os_uint16_t put_index;                  /* put index */

    os_data_item_t *queue;                  /* The pointer of data item. */

    os_list_node_t  suspended_push_list;    /* push task on this list. */    
    os_list_node_t  suspended_pop_list;     /* pop task on this list. */    

    void (*evt_notify)(struct os_data_queue *queue, os_uint32_t event);     /* event notify */
};
struct os_data_queue 说明
size 数据队列的大小
threshold 门限值,当队列中的数据项少于等于此门限时,读取数据会唤醒被阻塞的任务
get_index 数据项读取索引
put_index 数据项写入索引
queue 数据项队列头
suspended_push_list 阻塞在该数据队列上的发送任务
suspended_pop_list 阻塞在该数据队列上的接收任务
evt_notify 通知回调函数;在push时,若没有pop任务阻塞,该函数会被调用;在pop时被调用

API列表

接口 说明
os_data_queue_init 初始化数据队列
os_data_queue_deinit 反初始化数据队列
os_data_queue_push 向指定的数据队列中发送数据,当数据队列已满,则在指定的超时时间内挂起等待
os_data_queue_pop 从指定的数据队列中接收数据,如果数据队列为空,则在指定的时间内挂起等待
os_data_queue_peak 从指定的数据队列中读取但保留数据队列中的数据
os_data_queue_reset 恢复数据队列上挂起等待的所有任务

os_data_queue_init

该函数用于初始化数据队列,可以设定通知回调函数,函数原型如下:

os_err_t os_data_queue_init(os_data_queue_t *queue,
                            os_uint16_t size,
                            os_uint16_t threshold,
                            void (*evt_notify)(os_data_queue_t *queue, os_uint32_t event));
参数 说明
queue 数据队列句柄
size 数据队列的大小
threshold 门限值,当队列中的数据项少于等于此门限时,读取队列会唤醒被阻塞的任务
evt_notify 通知回调函数,在push或pop时被调用
返回 说明
OS_EOK 返回成功
OS_ENOMEM 失败,没有空间

os_data_queue_deinit

该函数用于反初始化数据队列,函数原型如下:

os_err_t os_data_queue_deinit(os_data_queue_t *queue);
参数 说明
queue 数据队列句柄
返回 说明
OS_EOK 成功

os_data_queue_push

该函数用于向指定的数据队列中发送数据,若数据队列满且需要等待,则当前任务阻塞。PUSH结束时若有POP任务阻塞,会唤醒POP任务;PUSH结束时若没有POP任务阻塞,则通知OS_DATAQUEUE_EVENT_PUSH。函数原型如下:

os_err_t os_data_queue_push(os_data_queue_t *queue, const void *data_ptr, os_size_t data_size, os_tick_t timeout);
参数 说明
queue 数据队列句柄
data_ptr 发送数据的起始地址
data_size 发送数据的大小
timeout 数据队列满时的超时等待时间;若为OS_IPC_WAITING_NO,则直接返回OS_ETIMEOUT;若为OS_IPC_WAITING_FOREVER,则永久等待直到数据队列有空余可用;若为其它值,则等待timeout时间或者直到数据队列有空余可用
返回 说明
OS_EOK 发送成功
OS_ETIMEOUT 发送超时

os_data_queue_pop

该函数用于从指定的数据队列中接收数据,若数据队列为空且需要等待,则当前任务阻塞。POP结束时若剩余数据项个数小于等于门限值,则(有PUSH任务阻塞时)唤醒被阻塞的PUSH任务,通知OS_DATAQUEUE_EVENT_THRESHOLD;POP结束时若剩余数据项大于门限值,则通知OS_DATAQUEUE_EVENT_POP。函数原型如下:

os_err_t os_data_queue_pop(os_data_queue_t *queue, const void** data_ptr, os_size_t *size, os_tick_t timeout);
参数 说明
queue 数据队列句柄
data_ptr 指向接收数据的地址
size 接收数据的大小
timeout 当数据队列为空时的超时等待时间;若为OS_IPC_WAITING_NO,则直接返回OS_ETIMEOUT;若为OS_IPC_WAITING_FOREVER,则永久等待直到数据队列有数据;若为其它值,则等待timeout时间或者直到数据队列有数据
返回 说明
OS_EOK 接收成功
OS_ETIMEOUT 接收超时

os_data_queue_peak

该函数用于从指定的数据队列中读取数据,但仍然保留数据队列中的该数据项,若数据队列为空则不等待直接退出,函数原型如下:

os_err_t os_data_queue_peak(os_data_queue_t *queue, const void** data_ptr, os_size_t *size);
参数 说明
queue 数据队列句柄
data_ptr 指向接收数据的地址
size 接收数据的大小
返回 说明
OS_EOK 接收成功
OS_EEMPTY 数据队列为空

os_data_queue_reset

该函数恢复数据队列上挂起等待的所有任务,函数原型如下:

void os_data_queue_reset(os_data_queue_t *queue);
参数 说明
queue 数据队列句柄
返回 说明

使用示例

数据队列使用示例

本例初始化数据队列后,创建了一个任务用于发送数据,另外一个任务用于接收数据,接收数据时采用了pop和peak两种方式,可以看到通过peak读取一个数据项后,该数据项仍然保留在数据队列中,通过pop读取该数据项后,无法再获得该数据项

#include <oneos_config.h>
#include <os_dbg.h>
#include <os_errno.h>
#include <os_task.h>
#include <shell.h>
#include <string.h>
#include <os_ipc.h>
#include <os_dataqueue.h>

#define TEST_TAG        "TEST"
#define TASK_STACK_SIZE 1024
#define TASK1_PRIORITY  15
#define TASK2_PRIORITY  16
#define TASK_TIMESLICE  10

#define STR_NUM         4

char *str[STR_NUM] = {
    "hello, world",
    "it's a new day",
    "it's a nice day",
    "it's a wonderful day"
    };

static os_data_queue_t dataqueue_test;


void test_dataqueue_notify(os_data_queue_t *queue, os_uint32_t event)
{
    LOG_W(TEST_TAG, "dataqueue notify:%d",event);
}

void task1_entry(void *para)
{
    os_uint32_t i = 0;
    const void *data_ptr = OS_NULL;
    os_size_t data_size = 0;

    while(1)
    {
        if (i < (STR_NUM/2))
        {
            if (OS_EOK == os_data_queue_peak(&dataqueue_test, &data_ptr, &data_size))
            {
                LOG_W(TEST_TAG, "task1 dataqueue peak ptr:%p size:%d str:%s", data_ptr, data_size, data_ptr);
            }
            else
            {
                LOG_W(TEST_TAG, "task1 dataqueue peak: empty");
            }
        }

        if (OS_EOK == os_data_queue_pop(&dataqueue_test, &data_ptr, &data_size, OS_IPC_WAITING_FOREVER))
        {
            LOG_W(TEST_TAG, "task1 dataqueue pop ptr :%p size:%d str:%s", data_ptr, data_size, data_ptr);
        }
        i++;
        os_task_sleep(200);
    }
}

void task2_entry(void *para)
{
    os_uint32_t i = 0;
    const void *data_ptr = OS_NULL;
    os_size_t data_size = 0;

    for (i  = 0; i < STR_NUM; i++) {
        data_ptr = str[i];
        data_size = strlen(str[i]) + 1;
        LOG_W(TEST_TAG, "task2 dataqueue push ptr:%p size:%d str:%s", data_ptr, data_size, data_ptr);
        if (OS_EOK != os_data_queue_push(&dataqueue_test, data_ptr, data_size, OS_IPC_WAITING_FOREVER))
        {
            LOG_W(TEST_TAG, "task2 dataqueue push ERR");
        }
        os_task_sleep(100);
    }
}

void dataqueue_sample(void)
{
    os_task_t *task1 = OS_NULL;
    os_task_t *task2 = OS_NULL;

    os_data_queue_init(&dataqueue_test, 10, 10, test_dataqueue_notify);

    task1 = os_task_create("task1", 
                           task1_entry, 
                           OS_NULL, 
                           TASK_STACK_SIZE, 
                           TASK1_PRIORITY, 
                           TASK_TIMESLICE);
    if (task1)
    {        
        LOG_W(TEST_TAG, "dataqueue_sample startup task1");
        os_task_startup(task1);
    }

    task2 = os_task_create("task2", 
                           task2_entry, 
                           OS_NULL, 
                           TASK_STACK_SIZE, 
                           TASK2_PRIORITY, 
                           TASK_TIMESLICE);
    if (task2)
    {        
        LOG_W(TEST_TAG, "dataqueue_sample startup task2");
        os_task_startup(task2);
    }
}

SH_CMD_EXPORT(test_dataqueue, dataqueue_sample, "test dataqueue");

运行结果如下:

sh />test_dataqueue 
W/TEST: dataqueue_sample startup task1
W/TEST: task1 dataqueue peak: empty
W/TEST: dataqueue_sample startup task2
W/TEST: task2 dataqueue push ptr:08027564 size:13 str:hello, world
W/TEST: dataqueue notify:3
W/TEST: task1 dataqueue pop ptr :08027564 size:13 str:hello, world
W/TEST: task2 dataqueue push ptr:0802759c size:15 str:it's a new day
W/TEST: dataqueue notify:2
W/TEST: task1 dataqueue peak ptr:0802759c size:15 str:it's a new day
W/TEST: dataqueue notify:3
W/TEST: task1 dataqueue pop ptr :0802759c size:15 str:it's a new day
W/TEST: task2 dataqueue push ptr:08027574 size:16 str:it's a nice day
W/TEST: dataqueue notify:2
W/TEST: task2 dataqueue push ptr:08027584 size:21 str:it's a wonderful day
W/TEST: dataqueue notify:2
W/TEST: dataqueue notify:3
W/TEST: task1 dataqueue pop ptr :08027574 size:16 str:it's a nice day
W/TEST: dataqueue notify:3
W/TEST: task1 dataqueue pop ptr :08027584 size:21 str:it's a wonderful day

results matching ""

    No results matching ""

    返回顶部