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

邮箱


简介

邮箱是一种典型的任务间通信机制。邮箱每次可以传递固定字节大小的邮件,且邮箱有缓冲区,可以缓存一定数量的邮件。邮箱没满的情况下,可以一直往邮箱里面发送邮件,邮箱满了可以选择超时等待;邮箱有邮件的情况下,可以从邮箱里面接收邮件,如果没有邮件,可以选择超时等待。

在本操作系统中,一封邮件的大小固定为4byte,所有可以直接发送32位数据。在32位系统上,一个指针大小是4byte,所以可以用邮箱来发送指针,而收发双方都按照相同的方式去解析指针指向的内容,就可以达到传送各种类型数据的功能。


重要定义及数据结构

结构体

struct os_mailbox
{
    struct os_ipc_object parent;                        /* Inherit from ipc_object. */

    os_uint32_t         *msg_pool;                      /* Start address of message buffer. */

    os_uint16_t          size;                          /* Size of message pool. */
    os_uint16_t          entry;                         /* Index of messages in msg_pool. */
    os_uint16_t          in_offset;                     /* Input offset of the message buffer. */
    os_uint16_t          out_offset;                    /* Output offset of the message buffer. */

    os_list_node_t       suspend_sender_task;           /* Sender thread suspended on this mailbox. */
};
struct os_mailbox重要参数 说明
msg_pool 邮箱缓冲区的起始地址
size 邮箱缓冲区的大小,以byte为单位
entry 邮箱中邮件的个数
in_offset 邮箱缓冲区中的输入偏移
out_offset 邮箱缓冲区中的输出偏移
suspend_sender_task 挂起在该邮箱上的发送任务

API列表

接口 说明
os_mb_init 以静态方式初始化邮箱,邮箱对象由使用者提供
os_mb_deinit 反初始化邮箱,与os_mb_init()匹配使用
os_mb_create 以动态方式创建并初始化邮箱,邮箱对象采用动态申请内存的方式获得
os_mb_destroy 销毁邮箱,与os_mb_create()匹配使用
os_mb_send 发送邮件
os_mb_recv 接收邮件
os_mb_control 控制或更改邮箱的行为属性

os_mb_init

该函数以静态的方式初始化邮箱,邮箱对象的内存空间和邮箱缓冲区都由使用者提供,函数原型如下:

os_err_t os_mb_init(os_mailbox_t  *mb,
                    const char    *name,                              
                    void          *msg_pool,
                    os_size_t     msg_pool_size,
                    os_ipc_flag_t flag);
参数 说明
mb 邮箱句柄
name 邮箱名字
msg_pool 邮箱缓冲区的起始地址
msg_pool_size 邮箱缓冲区的大小,以byte为单位
flag 标志,可以取OS_IPC_FLAG_FIFO和OS_IPC_FLAG_PRIO;当取值为OS_IPC_FLAG_FIFO时,等待的任务将按照先进先出的方式排队,先进入的任务先被唤醒;当取值为OS_IPC_FLAG_PRIO时,等待的任务将按照任务优先级排队,优先级高的任务先被唤醒
返回 说明
OS_EOK 初始化成功
OS_ERROR 初始化错误

os_mb_deinit

该函数用于反初始化邮箱,与os_mb_init()匹配使用,函数原型如下:

os_err_t os_mb_deinit(os_mailbox_t *mb);
参数 说明
mb 邮箱句柄
返回 说明
OS_EOK 反初始化成功

os_mb_create

该函数以动态的方式创建并初始化邮箱,其邮箱对象的内存空间和邮箱缓冲区都是通过动态申请内存获得,函数原型如下:

os_mailbox_t *os_mb_create(const char *name,  os_size_t max_mails, os_ipc_flag_t flag);
参数 说明
name 邮箱名字
max_mails 此邮箱支持的最大邮件个数
flag 标志,可以取OS_IPC_FLAG_FIFO和OS_IPC_FLAG_PRIO;当取值为OS_IPC_FLAG_FIFO时,等待的任务将按照先进先出的方式排队,先进入的任务先被唤醒;当取值为OS_IPC_FLAG_PRIO时,等待的任务将按照任务优先级排队,优先级高的任务先被唤醒
返回 说明
非OS_NULL 创建成功,返回邮箱句柄
OS_NULL 创建失败

os_mb_destroy

该函数用于销毁邮箱,并释放邮箱对象的内存空间和邮箱缓冲区的空间,函数原型如下:

os_err_t os_mb_destroy(os_mailbox_t *mb);
参数 说明
mb 邮箱句柄
返回 说明
OS_EOK 销毁成功

os_mb_send

该函数用于发送邮件,若邮箱已满且设定了等待时间,则当前发送任务阻塞,函数原型如下:

os_err_t os_mb_send(os_mailbox_t *mb, os_uint32_t value, os_tick_t timeout);
参数 说明
mb 邮箱句柄
value 邮件内容
timeout 当邮箱已满时,发送任务等待的超时时间;若为OS_IPC_WAITING_NO,则直接返回OS_EFULL;若为OS_IPC_WAITING_FOREVER,则永久等待直到邮箱有可用空间;若为其它值,则等待timeout时间或者直到邮箱有可用空间
返回 说明
OS_EOK 邮件发送成功
OS_EFULL 邮箱已满且未等待
OS_ETIMEOUT 邮箱已满且等待超时

os_mb_recv

该函数用于接收邮件,若邮箱为空且设定了等待时间,则当前接收任务阻塞,函数原型如下:

os_err_t os_mb_recv(os_mailbox_t *mb, os_uint32_t *value, os_tick_t timeout);
参数 说明
mb 邮箱句柄
value 指向接收的邮件内容
timeout 当邮箱为空时,接收任务等待的超时时间;若为OS_IPC_WAITING_NO,则直接返回OS_EEMPTY;若为OS_IPC_WAITING_FOREVER,则永久等待直到邮箱中有邮件;若为其它值,则等待timeout时间或者直到邮箱中有邮件
返回 说明
OS_EOK 邮件接收成功
OS_EEMPTY 邮箱为空且未等待
OS_ETIMEOUT 邮箱为空且等待超时

os_mb_control

该函数用于控制或改变邮箱的行为属性,函数原型如下:

os_err_t os_mb_control(os_mailbox_t *mb, os_ipc_cmd_t cmd, void *arg);
参数 说明
mb 邮箱句柄
cmd 控制命令,目前支持OS_IPC_CMD_RESET,该命令会唤醒所有阻塞在该邮箱上的任务,并重新初始化邮箱信息
返回 说明
OS_EOK 成功
OS_ERROR 失败

使用示例

静态邮箱使用示例

本例采用静态方式初始化了一个邮箱。然后创建了任务1,每隔一段时间发送一封邮件(32位整型数据),当邮箱满了之后,发送任务阻塞;之后创建任务2接收邮件,当读取邮件后,发送任务被唤醒可以继续发送邮件;当邮件被全部接收完成后,再次接收邮件时,接收任务会阻塞;后续发送任务每发送一封邮件,接收任务就被唤醒一次。

#include <oneos_config.h>
#include <os_dbg.h>
#include <os_errno.h>
#include <os_task.h>
#include <shell.h>
#include <os_mailbox.h>

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

#define MB_MAX_MAILS    10
#define MB_POLL_SIZE    (MB_MAX_MAILS * sizeof(os_uint32_t))

static char mb_pool[MB_POLL_SIZE];
static os_mailbox_t mb_static;

void task1_entry(void *para)
{
    os_uint32_t send_data = 0;

    while (1)
    {
        send_data++;
        LOG_W(TEST_TAG, "task1 send_data:%d", send_data);
        if(OS_EOK == os_mb_send(&mb_static, send_data, OS_IPC_WAITING_FOREVER))
        {
            LOG_W(TEST_TAG, "task1 send OK");
        }
        else
        {
            LOG_W(TEST_TAG, "task1 send err");
        }
        os_task_sleep(100);
    }
}

void task2_entry(void *para)
{
    os_uint32_t recv_data = 0;

    while (1)
    {        
        if (OS_EOK == os_mb_recv(&mb_static, &recv_data, OS_IPC_WAITING_FOREVER))
        {
            LOG_W(TEST_TAG, "task2 recv_data:%d", recv_data);
        }
    }
}

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

    os_mb_init(&mb_static, "mailbox_static", &mb_pool[0], MB_POLL_SIZE, OS_IPC_FLAG_FIFO);

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

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

SH_CMD_EXPORT(static_mailbox, mailbox_static_sample, "test staitc mailbox");

运行结果如下:

sh />static_mailbox
W/TEST: mailbox_static_sample startup task1
W/TEST: task1 send_data:1
W/TEST: task1 send OK
W/TEST: task1 send_data:2
W/TEST: task1 send OK
W/TEST: task1 send_data:3
W/TEST: task1 send OK
W/TEST: task1 send_data:4
W/TEST: task1 send OK
W/TEST: task1 send_data:5
W/TEST: task1 send OK
W/TEST: task1 send_data:6
W/TEST: task1 send OK
W/TEST: task1 send_data:7
W/TEST: task1 send OK
W/TEST: task1 send_data:8
W/TEST: task1 send OK
W/TEST: task1 send_data:9
W/TEST: task1 send OK
W/TEST: task1 send_data:10
W/TEST: task1 send OK
W/TEST: task1 send_data:11
W/TEST: mailbox_static_sample startup task2
W/TEST: task1 send OK
W/TEST: task2 recv_data:1
W/TEST: task2 recv_data:2
W/TEST: task2 recv_data:3
W/TEST: task2 recv_data:4
W/TEST: task2 recv_data:5
W/TEST: task2 recv_data:6
W/TEST: task2 recv_data:7
W/TEST: task2 recv_data:8
W/TEST: task2 recv_data:9
W/TEST: task2 recv_data:10
W/TEST: task2 recv_data:11
W/TEST: task1 send_data:12
W/TEST: task1 send OK
W/TEST: task2 recv_data:12
W/TEST: task1 send_data:13
W/TEST: task1 send OK
W/TEST: task2 recv_data:13
W/TEST: task1 send_data:14
W/TEST: task1 send OK
W/TEST: task2 recv_data:14
W/TEST: task1 send_data:15
W/TEST: task1 send OK
W/TEST: task2 recv_data:15

动态邮箱使用示例

本例采用动态的方式创建并初始化了一个邮箱;本例所展示的发送邮件的方式更为通用和更加灵活。在任务1中申请了一块空间,填充好要发送的数据后,将数据区域的指针作为邮件内容发送出去;在任务2中,接收到邮件内容后,将指针指向的数据按照相同的方式解析,之后释放申请的空间。

#include <oneos_config.h>
#include <os_dbg.h>
#include <os_errno.h>
#include <os_task.h>
#include <shell.h>
#include <string.h>
#include <os_memory.h>
#include <os_mailbox.h>

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

#define MB_MAX_MAILS    10
#define TEST_NAME_MAX   16
#define STUDENT_NUM     5

static os_mailbox_t *mb_dynamic;

struct student_score
{
    char                name[TEST_NAME_MAX];
    os_uint32_t         score;
};

void task1_entry(void *para)
{
    os_uint32_t i = 0;
    struct student_score *student_data = OS_NULL;
    char *name[STUDENT_NUM] = {"xiaoming", "xiaohua", "xiaoqiang", "xiaoli", "xiaofang"};
    os_uint32_t score[STUDENT_NUM] = {80, 85, 90, 95, 96};

    for (i = 0; i < STUDENT_NUM; i++)
    {
        student_data = os_malloc(sizeof(struct student_score));
        LOG_W(TEST_TAG, "task1 malloc ptr:%p", student_data);
        if (student_data)
        {
            memset(student_data->name, 0, TEST_NAME_MAX);
            strncpy(student_data->name, name[i], TEST_NAME_MAX);
            student_data->score = score[i];
            if(OS_EOK == os_mb_send(mb_dynamic, (os_uint32_t)student_data, OS_IPC_WAITING_FOREVER))
            {
                LOG_W(TEST_TAG, "task1 send -- name:%s score:%d", student_data->name, student_data->score);
            }
        }    
        os_task_sleep(100);
    }
}

void task2_entry(void *para)
{
    os_uint32_t recv_data = 0;

    while (1)
    {        
        if (OS_EOK == os_mb_recv(mb_dynamic, &recv_data, OS_IPC_WAITING_FOREVER))
        {
            LOG_W(TEST_TAG, "task2 recv -- name:%s score:%d", ((struct student_score *)recv_data)->name, ((struct student_score *)recv_data)->score);
            LOG_W(TEST_TAG, "task2 free ptr  :%p", (void*)recv_data);
            os_free((void*)recv_data);
        }
    }
}

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

    mb_dynamic = os_mb_create("mailbox_dynamic", MB_MAX_MAILS, OS_IPC_FLAG_FIFO);
    if(!mb_dynamic)
    {
        LOG_W(TEST_TAG, "mailbox_dynamic_sample mailbox create ERR");
        return;
    }

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

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

SH_CMD_EXPORT(dynamic_mailbox, mailbox_dynamic_sample, "test dynamic mailbox");

运行结果如下:

sh />dynamic_mailbox
W/TEST: mailbox_dynamic_sample startup task1
W/TEST: task1 malloc ptr:20007744
W/TEST: task1 send -- name:xiaoming score:80
W/TEST: task1 malloc ptr:20007768
W/TEST: task1 send -- name:xiaohua score:85
W/TEST: mailbox_dynamic_sample startup task2
W/TEST: task2 recv -- name:xiaoming score:80
W/TEST: task1 malloc ptr:20007a44
W/TEST: task1 send -- name:xiaoqiang score:90
W/TEST: task2 free ptr  :20007744
W/TEST: task2 recv -- name:xiaohua score:85
W/TEST: task2 free ptr  :20007768
W/TEST: task2 recv -- name:xiaoqiang score:90
W/TEST: task2 free ptr  :20007a44
W/TEST: task1 malloc ptr:20007744
W/TEST: task1 send -- name:xiaoli score:95
W/TEST: task2 recv -- name:xiaoli score:95
W/TEST: task2 free ptr  :20007744
W/TEST: task1 malloc ptr:20007744
W/TEST: task1 send -- name:xiaofang score:96
W/TEST: task2 recv -- name:xiaofang score:96
W/TEST: task2 free ptr  :20007744

results matching ""

    No results matching ""

    返回顶部