RT-Threadスタートガイドスタディノート-rt_mailboxの使用に精通している

前書き

  • メールボックスはメールの転送に使用され、誰もそれを受け取らなかった場合、一時的に保存されます。
  • RTスレッドメールボックスは、4バイト(32ビット)の値を送信します。この値は、値とポインター(32ビットMCU、ポインターは32ビット)で渡すことができます。
  • メールボックスの使用はメッセージキューよりも合理化されています。単純なコマンド送信の場合、メールボックスを使用でき、リソースの使用量を少なくすることができます。

2021-03-30_075724.png

 

関連API

  • rt-threadカーネルコード:rtthread.hでは、メールボックスのさまざまなAPIを見つけることができます
  • メールボックスAPIの実装(:)ipc.cは、スレッド間の一種の通信と見なすことができます。
  • メール:メールボックス関連のAPIは次のとおりです
rt_mb_init \ rt_mb_detach :静态初始化 \ 脱离,成对使用。
rt_mb_create \ rt_mb_delete : 动态创建 \ 删除,成对使用。
一般邮箱初始化后,就不再删除,可以使用静态初始化的方式。
rt_mb_send : 发送邮件,可以工作在在线程、回调函数里
rt_mb_send_wait :有超时的发送,工作在线程
rt_mb_recv :等待接收邮件,注意是队列式的接收,工作在线程里,循环等待接收
rt_mb_control : 提供一个初始化RESET邮箱的命令,不常用。
  • 開くと、メールボックスAPIはメッセージキューと非常によく似ています。

 

テストケース

  • このルーチンは、構造体ポインターを使用して、メールボックス内のスレッドとメッセージ間の通信に使用されます。構造データ、メモリを動的に適用する方法。
  • 受信メールボックスに注意してください。戻り値が== RT_EOK次のとおりであるかどうかを判断する必要があり ます。
/* 因为反正RT_EOK时为:0, 所以if判断时,需要 == RT_EOK。否则接收正确后,if不成立 */
if (rt_mq_recv(&t3_mq, &buf, sizeof(buf), RT_WAITING_FOREVER) == RT_EOK)
  • メールボックスの送信が正常かどうかを確認するために使用され、メモリアプリケーションとリリースがペアになっているかどうかを確認するために使用されます。
#include <rtthread.h>

/* 定义静态全局的邮箱:非指针 */
static struct rt_mailbox t1_mb;
static struct rt_mailbox t2_mb;
static struct rt_mailbox t3_mb;

/* 邮箱的大小(池子):一般一个消息为4个字节,这里采用数组 */
static rt_uint8_t msg_buf1[128];
static rt_uint8_t msg_buf2[128];
static rt_uint8_t msg_buf3[128];

/* 测试线程 */
#define THREAD1_STACK_SIZE   1024
#define THREAD1_PRIORITY     20
#define THREAD1_TIMESLICE    10

#define THREAD2_STACK_SIZE   1024
#define THREAD2_PRIORITY     20
#define THREAD2_TIMESLICE    10

#define THREAD3_STACK_SIZE   1024
#define THREAD3_PRIORITY     20
#define THREAD3_TIMESLICE    10

static rt_thread_t tid1 = RT_NULL;
static rt_thread_t tid2 = RT_NULL;
static rt_thread_t tid3 = RT_NULL;

extern void list_mem(void);

/* 测试传输的数据 */
struct mb_msg
{
    rt_uint8_t *data_ptr;
    rt_uint32_t data_size;
};

/* 邮箱初始化,使用前需要初始化 */
static void mb_init(void)
{
    rt_err_t result;

    /* 初始化邮箱1 */
    result = rt_mb_init(&t1_mb,
                        "t1mb",
                        &msg_buf1[0],            /* 内存池指向 msg_pool */
                        sizeof(msg_buf1) / 4,    /* 邮箱中的邮件数目,一封邮件占用4字节 */
                        RT_IPC_FLAG_FIFO);       /* 采用FIFO方式进行线程等待 */

    if (result != RT_EOK)
    {
        rt_kprintf("init thread1 mailbox failed.\n");
        return;
    }

    /* 初始化邮箱2 */
    result = rt_mb_init(&t2_mb,
                        "t2mb",
                        &msg_buf2[0],            /* 内存池指向 msg_pool */
                        sizeof(msg_buf2) / 4,    /* 邮箱中的邮件数目,一封邮件占用4字节 */
                        RT_IPC_FLAG_FIFO);       /* 采用FIFO方式进行线程等待 */

    if (result != RT_EOK)
    {
        rt_kprintf("init thread2 mailbox failed.\n");
        return;
    }

    /* 初始化邮箱3 */
    result = rt_mb_init(&t3_mb,
                        "t3mb",
                        &msg_buf3[0],            /* 内存池指向 msg_pool */
                        sizeof(msg_buf3) / 4,    /* 邮箱中的邮件数目,一封邮件占用4字节 */
                        RT_IPC_FLAG_FIFO);       /* 采用FIFO方式进行线程等待 */

    if (result != RT_EOK)
    {
        rt_kprintf("init thread3 mailbox failed.\n");
        return;
    }
    rt_kprintf("mb_init ok.\n");
}

/* 邮箱测试线程,按次序收与发 */
static void thread1_entry(void *param)
{
    struct mb_msg *msg_recv_ptr1;
    struct mb_msg *msg_send_ptr1;
    char sbuf[6] = {'T', 'a', 's', 'k', '1', '.'};

    while(1)
    {
        if (rt_mb_recv(&t1_mb, (rt_ubase_t *)&msg_recv_ptr1, RT_WAITING_FOREVER) == RT_EOK)
        {
            rt_kprintf("thread 1:[recv=%s], print 1.\n", msg_recv_ptr1->data_ptr);
            rt_thread_mdelay(10);
            rt_free(msg_recv_ptr1->data_ptr);
            list_mem();
            rt_free(msg_recv_ptr1);
            list_mem();
            rt_thread_mdelay(500);
            msg_send_ptr1 = (struct mb_msg *)rt_malloc(sizeof(struct mb_msg));
            msg_send_ptr1->data_size = sizeof(sbuf);
            msg_send_ptr1->data_ptr = (rt_uint8_t *)rt_malloc(msg_send_ptr1->data_size);
            rt_memcpy(msg_send_ptr1->data_ptr, sbuf, sizeof(sbuf));
            rt_kprintf("thread 1:[send=%s]\n", msg_send_ptr1->data_ptr);
            rt_mb_send(&t2_mb, (rt_uint32_t)msg_send_ptr1);
        }
    }
}

static void thread2_entry(void *param)
{
    struct mb_msg *msg_recv_ptr2;
    struct mb_msg *msg_send_ptr2;

    char sbuf[6] = {'T', 'a', 's', 'k', '2', '.'};

    while(1)
    {
        if (rt_mb_recv(&t2_mb, (rt_ubase_t *)&msg_recv_ptr2, RT_WAITING_FOREVER) == RT_EOK)
        {
            rt_kprintf("thread 2:[recv=%s], print 2.\n", msg_recv_ptr2->data_ptr);
            rt_thread_mdelay(10);
            rt_free(msg_recv_ptr2->data_ptr);
            list_mem();
            rt_free(msg_recv_ptr2);
            list_mem();
            rt_thread_mdelay(500);
            msg_send_ptr2 = (struct mb_msg *)rt_malloc(sizeof(struct mb_msg));
            msg_send_ptr2->data_size = sizeof(sbuf);
            msg_send_ptr2->data_ptr = (rt_uint8_t *)rt_malloc(msg_send_ptr2->data_size);
            rt_memcpy(msg_send_ptr2->data_ptr, sbuf, sizeof(sbuf));
            rt_kprintf("thread 2:[send=%s]\n", msg_send_ptr2->data_ptr);
            rt_mb_send(&t3_mb, (rt_uint32_t)msg_send_ptr2);
        }
    }
}

static void thread3_entry(void *param)
{
    struct mb_msg *msg_recv_ptr3;
    struct mb_msg *msg_send_ptr3;
    char sbuf[6] = {'T', 'a', 's', 'k', '3', '.'};

    while(1)
    {
        if (rt_mb_recv(&t3_mb, (rt_ubase_t *)&msg_recv_ptr3, RT_WAITING_FOREVER) == RT_EOK)
        {
            rt_kprintf("thread 3:[recv=%s], print 3.\n", msg_recv_ptr3->data_ptr);
            rt_thread_mdelay(10);
            rt_free(msg_recv_ptr3->data_ptr);
            list_mem();
            rt_free(msg_recv_ptr3);
            list_mem();
            rt_thread_mdelay(500);
            msg_send_ptr3 = (struct mb_msg *)rt_malloc(sizeof(struct mb_msg));
            msg_send_ptr3->data_size = sizeof(sbuf);
            msg_send_ptr3->data_ptr = (rt_uint8_t *)rt_malloc(msg_send_ptr3->data_size);
            rt_memcpy(msg_send_ptr3->data_ptr, sbuf, sizeof(sbuf));
            rt_kprintf("thread 3:[send=%s]\n", msg_send_ptr3->data_ptr);
            rt_mb_send(&t1_mb, (rt_uint32_t)msg_send_ptr3);
        }
    }
}

/* 初始化并启动邮箱的测试线程 */
static void task_init(void)
{
    struct mb_msg *msg_send_ptr;
    char sbuf[6] = {'T', 'a', 's', 'k', '1', '.'};
    rt_kprintf("%s: init start!\n", __func__);
    list_mem();
    rt_kprintf("%s: init end!\n", __func__);

    tid1 = rt_thread_create("task1",
                            thread1_entry,
                            RT_NULL,
                            THREAD1_STACK_SIZE,
                            THREAD1_PRIORITY,
                            THREAD1_TIMESLICE);

    
    tid2 = rt_thread_create("task2",
                            thread2_entry,
                            RT_NULL,
                            THREAD2_STACK_SIZE,
                            THREAD2_PRIORITY,
                            THREAD2_TIMESLICE);

    
    tid3 = rt_thread_create("task3",
                            thread3_entry,
                            RT_NULL,
                            THREAD3_STACK_SIZE,
                            THREAD3_PRIORITY,
                            THREAD3_TIMESLICE);

    if (tid1 != RT_NULL)
        rt_thread_startup(tid1);

    if (tid2 != RT_NULL)
        rt_thread_startup(tid2);

    if (tid3 != RT_NULL)
        rt_thread_startup(tid3);

    rt_thread_mdelay(500);
    msg_send_ptr = (struct mb_msg *)rt_malloc(sizeof(struct mb_msg));
    rt_kprintf("%s: rt_malloc 01\n", __func__);
    list_mem();
    rt_kprintf("%s: rt_malloc 01 end\n", __func__);
    msg_send_ptr->data_size = sizeof(sbuf);
    msg_send_ptr->data_ptr = (rt_uint8_t *)rt_malloc(msg_send_ptr->data_size);
    rt_kprintf("%s: rt_malloc 02", __func__);
    list_mem();
    rt_kprintf("%s: rt_malloc 02 end\n", __func__);
    rt_memcpy(msg_send_ptr->data_ptr, sbuf, sizeof(sbuf));
    
    rt_mb_send(&t1_mb, (rt_uint32_t)msg_send_ptr);
    rt_kprintf("task_init ok.\n");
}

/* MSH命令:启动邮箱测试例程 */
int mb_test(void)
{
    mb_init();
    task_init();
    return 1;
}

MSH_CMD_EXPORT(mb_test, mb test);

 

試験方法

  • シリアル入力:mb_test テストコマンド、メールボックスのテストを開始します
msh >mb_test
mb_init ok.
task_init: init start!
total memory: 89568
used memory : 10656
maximum allocated memory: 10656
task_init: init end!
task_init: rt_malloc 01
total memory: 89568
used memory : 14208
maximum allocated memory: 14208
task_init: rt_malloc 01 end
task_init: rt_malloc 02total memory: 89568
used memory : 14232
maximum allocated memory: 14232
task_init: rt_malloc 02 end
task_init ok.
msh >thread 1:[recv=Task1.###### ], print 1.
total memory: 89568
used memory : 14208
maximum allocated memory: 14232
total memory: 89568
used memory : 14184
maximum allocated memory: 14232
thread 1:[send=Task1.###### ]
thread 2:[recv=Task1.###### ], print 2.
total memory: 89568
used memory : 14208
maximum allocated memory: 14232
total memory: 89568
used memory : 14184
maximum allocated memory: 14232
thread 2:[send=Task2.###### ]
thread 3:[recv=Task2.###### ], print 3.
total memory: 89568
used memory : 14208
maximum allocated memory: 14232
total memory: 89568
used memory : 14184
maximum allocated memory: 14232
thread 3:[send=Task3.###### ]
thread 1:[recv=Task3.###### ], print 1.
total memory: 89568
used memory : 14208
maximum allocated memory: 14232
total memory: 89568
used memory : 14184
maximum allocated memory: 14232
thread 1:[send=Task1.###### ]
thread 2:[recv=Task1.###### ], print 2.
total memory: 89568
used memory : 14208
maximum allocated memory: 14232
total memory: 89568
used memory : 14184
  • メールボックスが正常に機能していること。

 

総括する

  • メールボックスとメッセージキューの両方をスレッド間の通信に使用できます。メッセージキューと比較して、メールボックス自体はより合理化されています。
  • メッセージキューと同様に、メールボックスの受信はスレッドに配置する必要があり、サスペンドスレッドは受信されないため、次を使用できます。RT_WAITING_FOREVER
  • メールボックスなどのスレッド間の通信に精通している場合は、カーネルコードの実装に精通し、その方法を知っている必要があります。

おすすめ

転載: blog.csdn.net/tcjy1000/article/details/115316471