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

摘要:
msgsnd用于将新消息添加到队列尾端。msgrcv用于从队列中取消息。

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

  一、系统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{
    longtype;
    char name[20];
    intage;
}Msg;
intmain()
{
    key_t key = ftok("/home/liudw",'6');
    printf("key:%x
",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{
    longtype;
    char name[20];
    intage;
}Msg;
intmain()
{
    key_t key = ftok("/home/liudw",'6');
    printf("key:%x
",key);
    int msgid =msgget(key,O_RDONLY);
    if(msgid<0)
    {   
        perror("msgget error!");
        exit(-1);
    }   
    Msg rcv;
    longtype;
    puts("please input type you want!");
    scanf("%ld",&type);
    msgrcv(msgid,&rcv,sizeof(rcv)-sizeof(type),type,0);
    printf("rcv--name:%s age:%d
",rcv.name,rcv.age);
    msgctl(msgid,IPC_RMID,NULL);
    return 0;
}

运行演示:

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

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

  三、详解ftok函数 

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

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

程序3-1如下:

--- snd.c ---

#include "my.h"
typedef struct{
    longtype;
    char name[20];
    intage;
}Msg;
intmain()
{
    key_t key = ftok("/home",'a');
    printf("key:%x
",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{
    longtype;
    char name[20];
    intage;
}Msg;
intmain()
{
    key_t key = ftok("/home",'a');
    printf("key:%x
",key);
    int msgid =msgget(key,O_RDONLY);
    if(msgid<0)
    {   
        perror("msgget error!");
        exit(-1);
    }   
    Msg rcv;
    longtype;
    puts("please input type you want!");
    scanf("%ld",&type);
    msgrcv(msgid,&rcv,sizeof(rcv)-sizeof(type),type,0);
    printf("rcv--name:%s age:%d
",rcv.name,rcv.age);
    msgctl(msgid,IPC_RMID,NULL);
    return 0;
}

运行演示如下图:

详解linux进程间通信-消息队列第3张 详解linux进程间通信-消息队列第4张

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

免责声明:文章转载自《详解linux进程间通信-消息队列》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇IDEA中 @override报错的解决方法(转载)pytorch学习问题汇总下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

WireShark抓包分析(二)

简述:本文介绍了抓包数据含义,有TCP报文、Http报文、DNS报文。如有错误,欢迎指正。 1、TCP报文 TCP:(TCP是面向连接的通信协议,通过三次握手建立连接,通讯完成时要拆除连接,由于TCP 是面向连接的所以只能用于点对点的通讯)源IP地址:发送包的IP地址;目的IP地址:接收包的IP地址;源端口:源系统上的连接的端口;目的端口:目的系统上的连...

Python操作 RabbitMQ、Redis、Memcache、SQLAlchemy

Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协...

ASP.NET Core 实现 MQTT通讯协议 Demo(开源库:MQTTnet)

1、什么是MQTT   MQTT(message queuing telemetry transport)是IBM开发的即时通讯协议,是一种发布/订阅极其轻量级的消息传输协议,专门为网络受限设备、低宽带以及高延迟和不可靠的网络而设计的。由于以上轻量级的特点,是实现智能家居的首选传输协议,相比于XMPP,更加轻量级而且占用宽带低。简单来说HQTT是一种通信...

PreTranslateMessage作用和用法

PreTranslateMessage作用和用法 PreTranslateMessage是消息在送给TranslateMessage函数之前被调用的,绝大多数本窗体的消息都要通过这里,比較经常使用,当须要在MFC之前处理某些消息时,经常要在这里加入代码. MFC消息控制流最具特色的地方是CWnd类的虚拟函数PreTranslateMessage()...

BSP模型

http://www.uml.org.cn/yunjisuan/201212191.asp Hama中最关键的就是BSP(Bulk Synchronous Parallel-“大型”同步模型)模型, BSP的概念由Valiant(1990)提出的,“块”同步模型,是一种异步MIMD-DM模型,支持消息传递系统,块内异步并行,块间显式同步,该模型基于一个m...

nc的基本用法

       nc(netcat) 被誉为网络安全界的‘瑞士军刀’,可以用于完成几乎涉及TCP、UDP或者Unix域套接字的任何事。它可以打开TCP连接,发送UDP报文,在任意的TCP和UDP端口监听,进行端口扫描,支持ipv6。不象telnet,nc能够更好地支持脚本,能够将错误消息分离到标准错误,而不是标准输出。nc有四种典型应用: 一、C/S模型 用...