0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

消息队列应用于线程间通信的简单例子

Linux大陆 来源:Linux大陆 2023-05-12 10:12 次阅读

大家好,我是LinuxZn。

在应用开发中,生产者,消费者的模型非常常见,一方产生数据并把数据放入队列中,而另一方从队列中取数据,先进先出。

应用:线程间通信/进程间通信。Hello系列 | 多线程编程基础!

Linux系统中提供了两种不同接口的消息队列:

POSIX消息队列。POSIX为可移植的操作系统接口

System V消息队列。System V 是 AT&T 的第一个商业UNIX版本(UNIX System III)的加强。

其中,POSIX消息队列可移植性较强,使用较广。

Linux系统中提供的消息队列一般应用于进行间通信,但也可以用于线程间通信。

本文介绍POSIX消息队列应用于线程间通信。

头文件:

#include/*ForO_*constants*/
#include/*Formodeconstants*/
#include

编译链接需要加上 -lr 链接。

Linux内核提供了一系列函数来使用消息队列:

/**
*@brief创建消息队列实例
*
*Detailedfunctiondescription
*
*@param[in]name:消息队列名称
*@param[in] oflag:根据传入标识来创建或者打开一个已创建的消息队列
-O_CREAT:创建一个消息队列
-O_EXCL:检查消息队列是否存在,一般与O_CREAT一起使用
-O_CREAT|O_EXCL:消息队列不存在则创建,已存在返回NULL
-O_NONBLOCK:非阻塞模式打开,消息队列不存在返回NULL
-O_RDONLY:只读模式打开
-O_WRONLY:只写模式打开
-O_RDWR:读写模式打开
*@param[in] mode:访问权限
*@param[in] attr:消息队列属性地址
*
*@return成功返回消息队列描述符,失败返回-1,错误码存于error中
*/
mqd_tmq_open(constchar*name,intoflag,mode_tmode,structmq_attr*attr);

/**
*@brief无限阻塞方式接收消息
*
*Detailedfunctiondescription
*
*@param[in]mqdes:消息队列描述符
*@param[in] msg_ptr:消息体缓冲区地址
*@param[in] msg_len:消息体长度,长度必须大于等于消息属性设定的最大值
*@param[in] msg_prio:消息优先级
*
*@return成功返回消息长度,失败返回-1,错误码存于error中
*/
mqd_tmq_receive(mqd_tmqdes,char*msg_ptr,size_tmsg_len,unsigned*msg_prio);

/**
*@brief指定超时时间阻塞方式接收消息
*
*Detailedfunctiondescription
*
*@param[in]mqdes:消息队列描述符
*@param[in] msg_ptr:消息体缓冲区地址
*@param[in] msg_len:消息体长度,长度必须大于等于消息属性设定的最大值
*@param[in] msg_prio:消息优先级
*@param[in] abs_timeout:超时时间
*
*@return成功返回消息长度,失败返回-1,错误码存于error中
*/
mqd_tmq_timedreceive(mqd_tmqdes,char*msg_ptr,size_tmsg_len,unsigned*msg_prio,conststructtimespec*abs_timeout);

/**
*@brief无限阻塞方式发送消息
*
*Detailedfunctiondescription
*
*@param[in]mqdes:消息队列描述符
*@param[in] msg_ptr:待发送消息体缓冲区地址
*@param[in] msg_len:消息体长度
*@param[in] msg_prio:消息优先级
*
*@return成功返回0,失败返回-1
*/
mqd_tmq_send(mqd_tmqdes,constchar*msg_ptr,size_tmsg_len,unsignedmsg_prio);

/**
*@brief指定超时时间阻塞方式发送消息
*
*Detailedfunctiondescription
*
*@param[in]mqdes:消息队列描述符
*@param[in] msg_ptr:待发送消息体缓冲区地址
*@param[in] msg_len:消息体长度
*@param[in] msg_prio:消息优先级
*@param[in] abs_timeout:超时时间
*
*@return成功返回0,失败返回-1
*/
mqd_tmq_timedsend(mqd_tmqdes,constchar*msg_ptr,size_tmsg_len,unsignedmsg_prio,conststructtimespec*abs_timeout);

/**
*@brief关闭消息队列
*
*Detailedfunctiondescription
*
*@param[in]mqdes:消息队列描述符
*
*@return成功返回0,失败返回-1
*/
mqd_tmq_close(mqd_tmqdes);

/**
*@brief分离消息队列
*
*Detailedfunctiondescription
*
*@param[in]name:消息队列名称
*
*@return成功返回0,失败返回-1
*/
mqd_tmq_unlink(constchar*name);

例子:线程1不断给线程2发送字符串数据。

#include
#include
#include
#include
#include
#include/*ForO_*constants*/
#include/*Formodeconstants*/
#include

#defineMQ_MSG_MAX_SIZE512///< 最大消息长度 
#define MQ_MSG_MAX_ITEM    5  ///< 最大消息数目

static pthread_t s_thread1_id;
static pthread_t s_thread2_id;
static unsigned char s_thread1_running = 0;
static unsigned char s_thread2_running = 0;

static mqd_t s_mq;
static char send_msg[10] = "hello";

void *thread1_fun(void *arg)
{
    int ret = 0;

    s_thread1_running = 1;
    while (s_thread1_running)  
    {
  ret = mq_send(s_mq, send_msg, sizeof(send_msg), 0);
  if (ret < 0)
  {
         perror("mq_send error");
  }
        printf("send msg = %s
", send_msg);
        usleep(100 * 1000);
    }
    
    pthread_exit(NULL);
}

void *thread2_fun(void *arg)
{
 char  buf[MQ_MSG_MAX_SIZE];
 int recv_size = 0;

    s_thread2_running = 1;
    while (s_thread2_running)
    {
  recv_size = mq_receive(s_mq, &buf[0], sizeof(buf), NULL);
  if (-1 != recv_size)
  {
   printf("receive msg = %s
", buf);
  }
  else
  {
   perror("mq_receive error");
   break;
  }

        usleep(100 * 1000);
    }
    
    pthread_exit(NULL);
}

int main(void)
{
    int ret = 0;
    struct mq_attr attr;

    ///< 创建消息队列
    memset(&attr, 0, sizeof(attr));
    attr.mq_maxmsg = MQ_MSG_MAX_ITEM;
    attr.mq_msgsize = MQ_MSG_MAX_SIZE;
    attr.mq_flags = 0;
    s_mq = mq_open("/mq", O_CREAT|O_RDWR, 0777, &attr);
 if(-1 == s_mq)
    {
        perror("mq_open error");
        return -1;
    }

    ///< 创建线程1
    ret = pthread_create(&s_thread1_id, NULL, thread1_fun, NULL);
    if (ret != 0)
    {
        printf("thread1_create error!
");
        exit(EXIT_FAILURE);
    }
    ret = pthread_detach(s_thread1_id);
    if (ret != 0)
    {
        printf("s_thread1_id error!
");
        exit(EXIT_FAILURE);
    }

    ///< 创建线程2
    ret = pthread_create(&s_thread2_id, NULL, thread2_fun, NULL);
    if (ret != 0)
    {
        printf("thread2_create error!
");
        exit(EXIT_FAILURE);
    }
    ret = pthread_detach(s_thread2_id);
    if (ret != 0)
    {
        printf("s_thread2_id error!
");
        exit(EXIT_FAILURE);
    }

    while (1)
    {
        sleep(1);
    }

    return 0;
}

编译、运行:

09a74950-efe5-11ed-90ce-dac502259ad0.png

以上就是本次的分享,如果文章有帮助,麻烦帮忙转发,谢谢!

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 通信
    +关注

    关注

    18

    文章

    5706

    浏览量

    134396
  • Linux
    +关注

    关注

    87

    文章

    10990

    浏览量

    206736
  • Linux系统
    +关注

    关注

    4

    文章

    567

    浏览量

    26920
  • 线程
    +关注

    关注

    0

    文章

    489

    浏览量

    19495
  • 消息队列
    +关注

    关注

    0

    文章

    31

    浏览量

    2921

原文标题:消息队列应用于线程间通信 | 简单例子

文章出处:【微信号:Linux大陆,微信公众号:Linux大陆】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    线程编程之三 线程通讯

    线程通信不但是难以避免的,而且在多线程编程中也是复杂和频繁的,下面将进行说明。使用全局变量进行通信由于属于同一个进程的各个
    发表于 10-22 11:43

    不同VI队列通信问题

    使用生产者消费者循环做多VI的数据通信,VI1中处理的数据进入VI2的队列中,请问VI2的队列如何在VI1中引用?点队列引用右键创建常量么
    发表于 12-25 14:32

    Linux多线程线程同步

    。同一进程内的线程共享进程的地址空间。通信:进程通信IPC,线程可以直接读写进程数据段(如全
    发表于 12-08 14:14

    IOT-OS之RT-Thread--- 线程同步与线程通信

    rt_thread,下面要介绍线程的同步与通信线程同步对象rt_sem / rt_mutex / rt_event和
    发表于 07-02 06:15

    TWEN-ASR ONE 语音识别系列教程(4)---多线程与消息队列使用

    的节奏不一样,如下图所示。从实验现象我们可以看出,两个线程的程序都在运行,并且互不干扰。 二、消息队列的使用与测试2.1消息队列使用说明     消息队列是一种常
    发表于 07-02 16:27

    请问ESP32双核如何使用队列进行任务通信

    队列是什么?ESP32双核如何使用队列进行任务通信
    发表于 01-14 07:24

    如何将邮箱、消息队列与信号用于RT-Thread线程通信

    1、RT-Thread操作系统的线程通信RT-Thread 操作系统的邮箱用于线程
    发表于 04-15 15:36

    【rtthread学习笔记系列】第三篇:线程是怎样进行通信

    一、线程通信在裸机中使用全局变量进行功能通信,rtthread提供了三个工具用于
    发表于 04-22 11:20

    RT-thread内核之进程通信设计实现

    、互斥锁、事件、邮箱、消息队列。其中前5个主要表现为线程同步,邮箱与消息队列表现为线程
    发表于 09-01 15:13

    RTT多线程通信机制有哪几种及推荐?

    针对采用RTT OS ,启动了4个线程,两个串口读写线程(数据>10byte以上) 一个触摸按键线程 一个显示线程,针对这几个线程间数据传输
    发表于 04-07 15:52

    FreeRTOS队列创建任务通信的基本应用程序

    应用程序 : 此代码是 FreeRTOS 队列创建任务通信的基本应用程序 。 BSP 版本: M480系列 BSP CMSIS V3.04.000 硬件: NuMaker-PFM-M487
    发表于 08-22 07:12

    Java多线程总结之Queue

    在Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列。Java提供的线程安全的Queue可以分为 阻塞队列和非阻
    发表于 11-28 16:14 3152次阅读
    Java多<b class='flag-5'>线程</b>总结之Queue

    嵌入式环形队列和消息队列的实现

    嵌入式环形队列和消息队列是实现数据缓存和通信的常见数据结构,广泛应用于嵌入式系统中的通信协议和领域。
    的头像 发表于 04-14 11:52 1062次阅读

    嵌入式环形队列和消息队列是如何去实现的?

    嵌入式环形队列和消息队列是实现数据缓存和通信的常见数据结构,广泛应用于嵌入式系统中的通信协议和领域。
    发表于 05-20 14:55 671次阅读

    如何实现一个多读多写的线程安全的无锁队列

    加锁。那么如何实现一个多读多写的线程安全的无锁队列呢? 互斥锁:mutexqueue(太简单不介绍了) 互斥锁+条件变量:blockqueue(太简单不介绍了) 内存屏障:lockfr
    的头像 发表于 11-08 15:25 450次阅读
    如何实现一个多读多写的<b class='flag-5'>线程</b>安全的无锁<b class='flag-5'>队列</b>