zoukankan      html  css  js  c++  java
  • rt_thread线程间通讯

    邮箱与消息队列:

    邮箱:开销小,效率高(每次4字节,32位任意值或指向缓冲区的指针),相当于MQTT中的代理。一(发)对多(收)关系;

       分阻塞(邮箱不存在或超时参数不为0)和非阻塞(中断与线程间发送消息的有效手段)

              发送满等待与接收空等待。

       

    创建邮箱:分配内存大小=邮件数*4

    /* 邮箱控制块 */
    static struct rt_mailbox mb;
    /* 用于放邮件的内存池 */
    static char mb_pool[128];
    
    static char mb_str1[] = "I'm a mail!";
    static char mb_str2[] = "this is another mail!";
    static char mb_str3[] = "over";
    
    ALIGN(RT_ALIGN_SIZE)
    static char thread1_stack[1024];
    static struct rt_thread thread1;
    
    /* 线程 1 入口 */
    static void thread1_entry(void *parameter)
    {
        char *str;
    
        while (1)
        {
            rt_kprintf("thread1: try to recv a mail
    ");
    
            /* 从邮箱中收取邮件 */
            if (rt_mb_recv(&mb, (rt_uint32_t *)&str, RT_WAITING_FOREVER) == RT_EOK)
            {
                rt_kprintf("thread1: get a mail from mailbox, the content:%s
    ", str);
                if (str == mb_str3)/*指针比较*/
                    break;
    
                /* 延时 100ms */
                rt_thread_mdelay(100);
            }
        }
        /* 执行邮箱对象脱离 */
        rt_mb_detach(&mb);
    }
    邮箱收发内容:
    struct msg
    {
        rt_uint8_t *data_ptr;
        rt_uint32_t data_size;
    };
    
    struct msg* msg_ptr;
    
    msg_ptr = (struct msg*)rt_malloc(sizeof(struct msg));
    msg_ptr->data_ptr = ...; /* 指向相应的数据块地址 */
    msg_ptr->data_size = len; /* 数据块的长度 */
    /* 发送这个消息指针给 mb 邮箱 */
    rt_mb_send(mb, (rt_uint32_t)msg_ptr);
    
    
    struct msg* msg_ptr;
    if (rt_mb_recv(mb, (rt_uint32_t*)&msg_ptr) == RT_EOK)
    {
        /* 在接收线程处理完毕后,需要释放相应的内存块 */
        rt_free(msg_ptr);
    }
    消息队列:是邮箱的扩展,用于线程间的消息交换、使用串口/中断服务接收不定长数据,是一种异步通讯。
    msg_queue_head 和 msg_queue_tail;/msg_queue_free

    发送队列:插在尾部。

    等待方式发送队列:如果满则按超时等待

    发送紧急队列:rt_mq_urgent插在队首

    等待队列:

    接收队列:

    使用场合一:发送消息

    void send_op(void *data, rt_size_t length)
    {
        struct msg msg_ptr;
    
        msg_ptr.data_ptr = data;  /* 指向相应的数据块地址 */
        msg_ptr.data_size = length; /* 数据块的长度 */
    
        /* 发送这个消息指针给 mq 消息队列 */
        rt_mq_send(mq, (void*)&msg_ptr, sizeof(struct msg));
    }
    
    /*消息队列是直接的数据内容复制,所以都采用了局部变量的方式保存消息结构体,这样也就免去动态内存分配的烦恼了*/
    void message_handler()
    {
        struct msg msg_ptr; /* 用于放置消息的局部变量 */
    
        /* 从消息队列中接收消息到 msg_ptr 中 */
        if (rt_mq_recv(mq, (void*)&msg_ptr, sizeof(struct msg)) == RT_EOK)
        {
            /* 成功接收到消息,进行相应的数据处理 */
        }
    }

    使用场合2:同步消息:可采用队列+邮箱/信号量方式:

    信号

    信号(又称为软中断信号),在软件层次上是对中断机制的一种模拟,在原理上,一个线程收到一个信号与处理器收到一个中断请求可以说是类似的。线程之间可以互相通过调用 rt_thread_kill() 发送软中断信号。rt_sigset_t,应用程序能够使用的信号为 SIGUSR1(10)和 SIGUSR2(12)。

    用途:用来通知线程发生了异步事件,用做线程之间的异常通知、应急处理

    对信号的处理:忽略SIG_IGN/默认系统处理SIG_DFL/回调函数

    安装信号:该线程要处理什么信号,加入到来后如何处理,建立信号与回调之间的关系。

    阻塞/屏蔽信号:相当于中断失能

    解除阻塞:使能

    发送信号:中断发送int rt_thread_kill(rt_thread_t tid, int sig);//给某个线程哪个信号。

    等待信号:没等到则阻塞。也可以不用

    使用方法:线程1安装信号并接触信号,并正常进行;线程2发信号给线程1则会直接调用handler处理函数。

  • 相关阅读:
    @Autowired 与@Resource的区别(详细)
    mvn clean compile package install deploy
    Android Studio 之 NDK篇
    cmake处理多源文件目录的方法
    linux CMakeLists.txt 语法
    在 Android Studio 2.2 中愉快地使用 C/C++
    MySql 模糊查询
    C++静态库与动态库详解
    配置Yum源repo文件及搭建本地Yum服务器
    yum命令
  • 原文地址:https://www.cnblogs.com/jieruishu/p/12813779.html
Copyright © 2011-2022 走看看