详解linux进程间通信-消息队列

简介: 前言:前面讨论了信号、管道的进程间通信方式,接下来将讨论消息队列。  一、系统V IPC  三种系统V IPC:消息队列、信号量以及共享内存(共享存储器)之间有很多相似之处。  每个内核中的 I P C结构(消息队列、信号量或共享存储段)都用一个非负整数的标识符( i d e n t i f i e r )加以引用。

前言:前面讨论了信号、管道的进程间通信方式,接下来将讨论消息队列。

  一、系统V IPC

  三种系统V IPC:消息队列、信号量以及共享内存(共享存储器)之间有很多相似之处。

  每个内核中的 I P C结构(消息队列、信号量或共享存储段)都用一个非负整数的标识符
( i d e n t i f i e r )加以引用。

  无论何时创建I P C结构(调用m s g g e ts e m g e ts h m g e t,都应指定一个关键字(k e y),关
键字的数据类型由系统规定为 k e y _ t,通常在头文件< s y s / t y p e s . h >中被规定为长整型。关键字由
内核变换成标识符。

  以上简单介绍了IPC,对接下来介绍的消息队列、信号量和共享内存有助于理解。

  二、消息队列

  1、简介

  消息队列是消息的链接表 ,存放在内核中并由消息队列标识符标识。我们将称消息队列为
“队列”,其标识符为“队列 I D”。 m s g g e t用于创建一个新队列或打开一个现存的队列。 m s g s n d
用于将新消息添加到队列尾端。每个消息包含一个正长整型类型字段,一个非负长度以及实际
数据字节(对应于长度),所有这些都在将消息添加到队列时,传送给 m s g s n dm s g r c v用于从
队列中取消息。我们并不一定要以先进先出次序取消息,也可以按消息的类型字段取消息。

  2、函数介绍

  • ftok函数

#include <sys/types.h>
#include <sys/ipc.h>

key_t ftok(const char *pathname, int proj_id);//“/home/linux” , 'a'
功能:生成一个key(键值)

  • msgget函数

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgget(key_t key, int msgflg);

功能:创建或取得一个消息队列对象
返回:消息队列对象的id 同一个key得到同一个对象
格式:msgget(key,flag|mode);
flag:可以是0或者IPC_CREAT(不存在就创建)
mode:同文件权限一样

  • msgsnd函数

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:将msgp消息写入标识为msgid的消息队列
msgp:
struct msgbuf {
long mtype; /* message type, must be > 0 */消息的类型必须>0
char mtext[1]; /* message data */长度随意
};

msgsz:要发送的消息的大小 不包括消息的类型占用的4个字节
msgflg: 如果是0 当消息队列为满 msgsnd会阻塞
如果是IPC_NOWAIT 当消息队列为满时 不阻塞 立即返回

返回值:成功返回id 失败返回-1

  • msgrcv函数

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
int msgflg);

功能:从标识符为msgid的消息队列里接收一个指定类型的消息 并 存储于msgp中 读取后 把消息从消息队列中删除
msgtyp:为 0 表示无论什么类型 都可以接收
msgp:存放消息的结构体
msgsz:要接收的消息的大小 不包含消息类型占用的4字节
msgflg:如果是0 标识如果没有指定类型的消息 就一直等待
如果是IPC_NOWAIT 则表示不等待

  • msgctl函数

int msgctl(int msqid, int cmd, struct msqid_ds *buf);
msgctl(msgid,IPC_RMID,NULL);//删除消息队列对象

  程序2-2将简单演示消息队列:

  ---  snd.c  ---

#include "my.h"

typedef struct{
    long type;
    char name[20];
    int age;
}Msg;

int main()
{
    key_t key = ftok("/home/liudw",'6');
    printf("key:%x\n",key);

    int msgid = msgget(key,IPC_CREAT|O_WRONLY|0777);
    if(msgid<0)
    {   
        perror("msgget error!");
        exit(-1);
    }   

    Msg m;
    puts("please input your type name age:");
    scanf("%ld%s%d",&m.type,m.name,&m.age);
    msgsnd(msgid,&m,sizeof(m)-sizeof(m.type),0);

    return 0;
}

  ---  rcv.c  ---

#include "my.h"
 
typedef struct{
    long type;
    char name[20];
    int age;
}Msg;

int main()
{
    key_t key = ftok("/home/liudw",'6');
    printf("key:%x\n",key);

    int msgid = msgget(key,O_RDONLY);
    if(msgid<0)
    {   
        perror("msgget error!");
        exit(-1);
    }   

    Msg rcv;
    long type;
    puts("please input type you want!");
    scanf("%ld",&type);

    msgrcv(msgid,&rcv,sizeof(rcv)-sizeof(type),type,0);
    printf("rcv--name:%s age:%d\n",rcv.name,rcv.age);

    msgctl(msgid,IPC_RMID,NULL);
    return 0;
}

  运行演示:

  三、详解ftok函数 

  • ftok根据路径名,提取文件信息,再根据这些文件信息及project ID合成key,该路径可以随便设置。
  • 该路径是必须存在的,ftok只是根据文件inode在系统内的唯一性来取一个数值,和文件的权限无关。
  • proj_id是可以根据自己的约定,随意设置。这个数字,有的称之为project ID; 在UNIX系统上,它的取值是1到255;

 

  为了验证以上观点,对程序2-2稍作修改,将路径和proj_id修改:

  程序3-1如下:

  ---  snd.c  ---

#include "my.h"

typedef struct{
    long type;
    char name[20];
    int age;
}Msg;

int main()
{
    key_t key = ftok("/home",'a');
    printf("key:%x\n",key);

    int msgid = msgget(key,IPC_CREAT|O_WRONLY|0777);
    if(msgid<0)
    {   
        perror("msgget error!");
        exit(-1);
    }   

    Msg m;
    puts("please input your type name age:");
    scanf("%ld%s%d",&m.type,m.name,&m.age);
    msgsnd(msgid,&m,sizeof(m)-sizeof(m.type),0);

    return 0;
}

  ---  rcv.c  ---

#include "my.h"

typedef struct{
    long type;
    char name[20];
    int age;
}Msg;

int main()
{
    key_t key = ftok("/home",'a');
    printf("key:%x\n",key);

    int msgid = msgget(key,O_RDONLY);
    if(msgid<0)
    {   
        perror("msgget error!");
        exit(-1);
    }   

    Msg rcv;
    long type;
    puts("please input type you want!");
    scanf("%ld",&type);

    msgrcv(msgid,&rcv,sizeof(rcv)-sizeof(type),type,0);
    printf("rcv--name:%s age:%d\n",rcv.name,rcv.age);

    msgctl(msgid,IPC_RMID,NULL);
    return 0;
}

  运行演示如下图:

 

  总结:主要介绍了进程间通信的消息队列,有疑问可以留言,一定即时解答。

 

作者: 柳德维

-------------------------------------------

个性签名:独学而无友,则孤陋而寡闻。做一个灵魂有趣的人!

如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!

万水千山总是情,打赏一分行不行,所以如果你心情还比较高兴,也是可以扫码打赏博主,哈哈哈(っ•̀ω•́)っ⁾⁾!

目录
相关文章
|
1月前
|
消息中间件 存储 网络协议
从零开始掌握进程间通信:管道、信号、消息队列、共享内存大揭秘
本文详细介绍了进程间通信(IPC)的六种主要方式:管道、信号、消息队列、共享内存、信号量和套接字。每种方式都有其特点和适用场景,如管道适用于父子进程间的通信,消息队列能传递结构化数据,共享内存提供高速数据交换,信号量用于同步控制,套接字支持跨网络通信。通过对比和分析,帮助读者理解并选择合适的IPC机制,以提高系统性能和可靠性。
132 14
|
11天前
|
消息中间件 Linux
Linux中的System V通信标准--共享内存、消息队列以及信号量
希望本文能帮助您更好地理解和应用System V IPC机制,构建高效的Linux应用程序。
79 48
|
4天前
|
存储 网络协议 Linux
【Linux】进程IO|系统调用|open|write|文件描述符fd|封装|理解一切皆文件
本文详细介绍了Linux中的进程IO与系统调用,包括 `open`、`write`、`read`和 `close`函数及其用法,解释了文件描述符(fd)的概念,并深入探讨了Linux中的“一切皆文件”思想。这种设计极大地简化了系统编程,使得处理不同类型的IO设备变得更加一致和简单。通过本文的学习,您应该能够更好地理解和应用Linux中的进程IO操作,提高系统编程的效率和能力。
50 34
|
8天前
|
消息中间件 Linux C++
c++ linux通过实现独立进程之间的通信和传递字符串 demo
的进程间通信机制,适用于父子进程之间的数据传输。希望本文能帮助您更好地理解和应用Linux管道,提升开发效率。 在实际开发中,除了管道,还可以根据具体需求选择消息队列、共享内存、套接字等其他进程间通信方
40 16
|
1月前
|
消息中间件 Linux
Linux:进程间通信(共享内存详细讲解以及小项目使用和相关指令、消息队列、信号量)
通过上述讲解和代码示例,您可以理解和实现Linux系统中的进程间通信机制,包括共享内存、消息队列和信号量。这些机制在实际开发中非常重要,能够提高系统的并发处理能力和数据通信效率。希望本文能为您的学习和开发提供实用的指导和帮助。
118 20
|
2月前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
121 13
|
2月前
|
SQL 运维 监控
南大通用GBase 8a MPP Cluster Linux端SQL进程监控工具
南大通用GBase 8a MPP Cluster Linux端SQL进程监控工具
|
7月前
|
消息中间件 C语言 RocketMQ
消息队列 MQ操作报错合集之出现"Connection reset by peer"的错误,该如何处理
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。
|
7月前
|
消息中间件 Java C语言
消息队列 MQ使用问题之在使用C++客户端和GBase的ESQL进行编译时出现core dump,该怎么办
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。
|
3月前
|
消息中间件 存储 Kafka
MQ 消息队列核心原理,12 条最全面总结!
本文总结了消息队列的12个核心原理,涵盖消息顺序性、ACK机制、持久化及高可用性等内容。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。