[Linux]-进程间通信之消息队列

2023-10-29

目录

【消息队列的概述】

【消息队列的API】

1.获取系统唯一Key值(IPC键值)

2.创建消息队列

2.1查看消息队列的一些Linux命令

2.2消息队列的创建

3.消息的发送以及定义

3.1.通过消息队列发送信息

4.信息的接收

5.通过消息队列接受读取信息

6.消息队列的控制

【消息队列的总结】


【消息队列的概述】

之前我们使用过的管道比较适用于较少进程之间的通信,那么如果想要实现多个进程之前的通信的话,我们需要使用消息队列

消息队列具有如下特点

1.消息队列是消息的链表,存放于内存中,内核维护消息队列

2.消息队列中的消息是有类型的

3.消息队列中的消息是有格式的

4.消息队列可实现消息随机查询,并且不一定要遵循先进先出的顺序,而是每个进程可以按照感兴趣的类型进行读取

5.与管道相同,读出数据后,消息队列对应数据会被删除

6.每个管道都有消息队列标识符,在整个系统中是唯一的

7.消息队列允许一个或者多个进程向它写入或者读取数据

8.内核重启或者人为删除才会删除消息队列,否则会一直存在与系统中


【消息队列的API】

1.获取系统唯一Key值(IPC键值)

系统中可能会存在许多的消息队列,那么到底要怎么让进程区分到底是进入哪个消息队列呢,通过Key这个系统唯一值,可以选择想要进入的消息队列

这么理解,Key相当于假如聊天群聊的密码,如果你想要加入聊天,必须要有这个唯一的加入密码才可加入,不同的聊天群有不用的唯一密码(不同的消息队列有不用的密码)

其实这个Key值不仅是在消息队列中被使用,共享内存、信号等也使用

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

key_t ftok(const char *pathname, int proj_id);

功能

        获取项目相关唯一Key值

参数

        pathname:路径名

        proj_id:项目ID(非0整数)

返回值

        成功返回键值,失败-1

pathname这个参数可以随便设置的,因为Key值是通过所设置文件信息以及proj_id所合成Key值的,而proj_id这个数也是可以随便设置的。但是由于它只有8bit,也就是0-255.


2.创建消息队列

消息队列依赖于Key值创建,并且msgget函数并不仅仅是创建,如果消息队列已经存在,那么通过这个函数配合唯一键值就可以让不同的进程进入唯一的消息队列

#include <sys/msg.h>

int msgget(key_t key, int msgflg);

功能

        创建或者打开一个新的消息队列。即使进程不同,但是如果key值是相同的,那么也可以进入相同的消息队列,返回相同的消息队列标识符

参数

        key:IPC键值

        msgflg:表示函数的行为及消息队列的权限

        msgflag取值

                                IPC_CREAT:创建消息队列

                                IPC_EXCL:检测消息队列是否存在

                                位或权限位:消息队列位或权限位可以设置消息队列访问权限,和open函数的打开方式的mode_t一样

返回值

        成功:消息队列标识符

        失败:-1

2.1查看消息队列的一些Linux命令

ipcs -q                        

查看当前进程间通信之消息队列

解析

        ipc   就是进程间通信的意思

        s      search,搜索

        -q    消息队列的意思,还有很多可选项

ipcrm -q 队列号

删除指定的消息队列

解析

        ipc        进程间通信

        rm        删除,remove

        -q         消息队列


 下面是一些可选项(一般下面几个就是用到ipc键值的几种通信方式)

-m        共享内存

-q         消息队列

-s         信号量

-a         全部


2.2消息队列的创建

7e60d66f847d4738b1b43d80f3a2ea95.png

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int main(int argc, char const *argv[])
{

    //获取唯一键值
    key_t key = ftok("/",2023);
    printf("KEY为%#x\n",key);
    //通过key值生成消息队列
    int msg = msgget(key, IPC_CREAT | 0666 );
    printf("消息队列标识符为%d\n",msg);


    return 0;
}

3.消息的发送以及定义

消息队列中的信息是一个结构体,里面包含了消息类型以及消息正文两种类型,消息类型必须放在第一个,因为这个是每个进程读取消息的依据。消息正文可以有多个成员。

消息的结构体定义如下

typedef struct msgbuf
{
	long 	mtype;        //消息类型,必须放在第一个
	char	mtext[128];     //消息正文,可有多个
    .....
}MSG;

#include <sys/msg.h>

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

功能

        将新消息添加到消息队列

参数

        msqid:消息队列标识符

        msgp:待发送消息结构体地址

        msgsz:消息正文字数(结构体大小减去结构体中成员大小)

        msgflg:函数的控制属性

                      0:msgsnd调用阻塞直到满足条件为止

                      IPC_NOWAIT:若消息没有立即发送,调用该函数的进程会立即返回

返回值

        成功 0

        失败 -1  

        

3.1.通过消息队列发送信息

a869e8e8149b4b6fb92a54198bbd4544.png

int main(int argc, char const *argv[])
{

    //获取唯一键值
    key_t key = ftok("/",2023);
    printf("KEY为%#x\n",key);
    //通过key值生成消息队列
    int msg = msgget(key, IPC_CREAT | 0666 );
    printf("消息队列标识符为%d\n",msg);


    //编辑消息队列信息
    MSG _msg;
    memset(&msg,0,sizeof(msg));
    //不同进程通过消息队列获取信息的一依据
    _msg.mstype = 20;
    strcpy(_msg.mstext,"bob:hello msg");

    //发送消息
    msgsnd(msg,&_msg,sizeof(_msg)-sizeof(long),0);

    return 0;
}

4.信息的接收

#include <sys/msg.h>

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

功能

        从指定的消息队列标识符中接受信息,同时一旦接受成功,从消息队列中删除该信息。

参数

        msqid:消息队列标识符

        msgp:存放信息的结构体地址

        msgsz:消息正文的字节数

        msgtyp:感兴趣的消息类型(不同进程从消息队列中接受感兴趣数据的依据)

                        =0:接受队列第一个信息

                        >0:接受等于msgtyp的信息

                        <0:返回队列中消息类型值小于或者等于msgtyp的绝对值的值,若有多个,则取最小的值

        msgtyp注意事项

                        如果消息队列中有多个类型的信息,那么获取信息就是按照消息类型获取,而不是按照先进先出的情况下获取

                        如果某个消息类型是一样的并且有多条,那么按照先进先出的情况获取

        

        msgflg:

                        0:阻塞直到接收到信息为止

                        MSG_NOERROR:MSG NOERROR:若返回的消息字节数比nbytes字节数多,则消息就会截短到nbytes字节,且不通知消息发送进程

                        IPC_NOWAIT:调用进程会立即返回。若没有收到消息则立即返回-1

返回值

        成功:读取到字节个数

        失败:-1


5.通过消息队列接受读取信息

假设msgtyp的值为20,那么从消息队列读取数据的进程按照msgtyp为20作为感兴趣的值来读取数据。

43139b2f7c6c4464a92338cac6d0344b.png

发送信息方

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
typedef struct _msg
{
    long mstype;
    char mstext[128];
}MSG;



int main(int argc, char const *argv[])
{

    //获取唯一键值
    key_t key = ftok("/",2023);
    printf("KEY为%#x\n",key);
    //通过key值生成消息队列
    int msg = msgget(key, IPC_CREAT | 0666 );
    printf("消息队列标识符为%d\n",msg);


    //编辑消息队列信息
    MSG _msg;
    memset(&msg,0,sizeof(msg));
    //不同进程通过消息队列获取信息的一依据
    _msg.mstype = 20;
    strcpy(_msg.mstext,"bob:hello msg");

    //发送消息
    msgsnd(msg,&_msg,sizeof(_msg)-sizeof(long),0);
    printf("消息发送成功!\n");
    return 0;
}

接受信息方

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
typedef struct _msg
{
    long mstype;
    char mstext[128];
}MSG;

int main(int argc, char const *argv[])
{
    //获取唯一键值
    key_t key = ftok("/",2023);
    printf("KEY为%#x\n",key);
    //通过key值生成消息队列
    int msg = msgget(key, IPC_CREAT | 0666 );
    printf("消息队列标识符为%d\n",msg);


    //编辑消息队列信息
    MSG _msg;
    memset(&msg,0,sizeof(msg));

    //接受消息
    printf("lucy准备接受消息...\n");
    msgrcv(msg, &_msg, sizeof(_msg)-sizeof(long), 20,0);
    printf("接收到消息%s\n",_msg.mstext);





    return 0;
}

6.消息队列的控制

#include <sys/msg.h>

int msgctl(int msqid, int cmd, struct msqid_ds *buf);

功能

        对消息队列进行修改,修改属性或者删除消息队列等

参数

        msqid:消息队列标识符

        cmd:函数功能控制

        buf:msqid_ds数据类型地址,用来存放或者更改消息队列属性

        cmd

                IPC_RMID:删除该消息队列标识符的队列,从系统删除并破坏相关结构

                IPC_STAT:将该消息队列标识符表示的的消息队列各个元素值存到buf结构体中

                IPC_SET:将buf结构体中的数据设置到消息队列中

返回值

        成功 0

        失败 -1


【消息队列的总结】

如果一个进程想要访问或者创建一个消息队列,那么应该使用ftok获取一个唯一键值,然后通过这个IPC键值来访或者创建消息队列(多个进程通信就像是创建聊天群,进入聊天群的密码就是IPC键值,密码唯一)。只有成功进入消息队列才可以收发信息。

当进入消息队列,发送信息只能通过消息结构体struct msgbuf来接受,并且第一个成员一定要是mtype,因为这决定了进程从消息队列读取信息的依据,只读取感兴趣的类型(mtype)的数据。

管道比较适合进程比较少的通信,消息队列比较适合进程比较多的通信

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[Linux]-进程间通信之消息队列 的相关文章

随机推荐

  • 不需要第三方SDK就能实现Android图片的分享

    效果展示 原理分析 隐示意图 代码展示 MainActivity java package com wust shareappdemo import androidx appcompat app AppCompatActivity impo
  • 【C++】VS封装调用dll链接库

    在工程项目中 为了不暴露源代码和避免严重耦合 所以将代码封装成 dll二进制文件 以供项目调用 这几天 也是在看这些封装dll 并使用Java中的JNA调用c 的dll链接库中的函数 做个笔记 1 创建dll 新建项目 gt Win32项目
  • Spark SQL中的条件筛选以及case when表达

    baby 你就是我的唯一 Filter过滤 filter和where都可以进行过滤 可以根据指定的一个或多个条件或者SQL表达式来过滤掉DatFrame的行 在学习过滤之前 先来讲一个问题 在生产数据当中 可能会有很多的空数据 也就是Nul
  • 小波变换

    原文地址 1 小波变换 小波变换是一种信号的时间 尺度 时间 频率 分析方法 它具有多分辨分析的特点 而且在时频两域都具有表征信号局部特征的能力 是一种窗口大小固定不变但其形状可改变 时间窗和频率窗都可以改变的时频局部化分析方法 即在低频部
  • 题目十一:数据分类

    对一个数据a进行分类 分类方法是 此数据a 4个字节大小 的4个字节相加对一个给定值b取模 如果得到的结果小于一个给定的值c则数据a为有效类型 其类型为取模的值 如果得到的结果大于或者等于c则数据a为无效类型 比如一个数据a 0x01010
  • ansible安装k8s步骤及注意事项(在线安装)

    以下步骤都经本人实测 可以完美运行 官方参考网址 https github com gjmzj kubeasz Ansible了解 ansible是个什么东西呢 官方的title是 Ansibleis Simple IT Automatio
  • SpringBoot Maven多环境配置启动报错 APPLICATION FAILED TO START

    目录 Maven多环境配置 报错内容 分析问题 解决方法 filtering作用 修改结果 Maven多环境配置 profiles标签和properties同级
  • RabbitMQ重复消费

    造成重复消费的原因 MQ向消费者推送message 消费者向MQ返回ack 告知所推送的消息消费成功 但是由于网络波动等原因 可能造成消费者向MQ返回的ack丢失 MQ长时间 一分钟 收不到ack 于是会向消费者再次推送该条message
  • three.js点材质(PointsMaterial)常用属性设置

    一 前景回顾 上一章节简单介绍了下怎么使用点材质和点对象创建物体点对象和点材质介绍 点材质和点对象基本运用示例代码 import as THREE from three 导入轨道控制器 import OrbitControls from t
  • Open3D 点云旋转的轴角表示法(python详细过程版)

    目录 一 算法原理 二 代码实现 三 结果展示 四 实验数据 一 算法原理 见 点云旋转的轴角表示法和罗德里格斯公式 二 代码实现 import open3d as o3d import numpy as np import copy 读取
  • 2020-10-09 Python基础学习第八天笔记

    文章目录 一 方法 1 私有方法和公共方法 2 property装饰器 3 继承 4 多态 polymorphism 一 方法 如果我们在类体中定义了多个重名的方法 只有最后一个方法有效 1 私有方法和公共方法 通常两个下划线开头的属性是私
  • python 关于文件操作——基础详细

    先看后赞 养成习惯 点赞收藏 人生辉煌 python 文件操作 文件读写 write read readlines readline 文件的相关操作 简单易懂 目录 1 文件操作 1 1 文件打开与关闭 1 1 1 打开文件 1 1 2 关
  • Unity3D的传送带和物体移动

    实现工厂流程的传送带传送物体的过程 包过一些基础的知识点 图片效果看原文 工程下载请看原文 https xygeng cn post 266 html 1 传送物体左右上下移动 gameObject transform Translate
  • sqlite3数据库交叉编译并移植到嵌入式开发环境步骤

    一 首先到http www sqlite org download html下载linux版本的源码 sqlite autoconf 3130000 tar gz 二 解压 tar xvzf sqlite autoconf 3130000
  • vue自定义指令---页面水印

    一些页面为了防止用户截图 可以添加水印 下面介绍以下思路 主要是创建一个新的节点作为水印 设置好水印的样式以后 再添加到目标节点上面去 水印 export default inserted el text let dom document
  • bootstrap导航栏鼠标移入展开

    bootstrap鼠标移入导航展开下拉菜单则加以下jq代码 function dropdown mouseover function this children a addClass show next ul addClass show d
  • 记录第一次部署streamlit应用

    网上相关教程很多 经过多方尝试 记录自己成功的方法 一 通过git将项目文件上传至github 参考教程 23条消息 部署项目到github Gao 的博客 CSDN博客 github部署项目 二 添加requirements 部署在Str
  • 计算机主机mac地址怎么查,怎么查看电脑的Mac地址

    第一种方法 利用dos命令查看Mac地址 1 点击 开始 菜单 在 搜索程序和文件 输入框 输入 cmd 会找到进入dos命令的cmd程序 然后回车 快捷方式 WIN R 在输入cmd 2 回车后 弹出命令符窗口 输入 ipconfig a
  • 技术积累 — Ellisys软件及抓包器用户使用指南

    一 前言 Ellisys号称是业界最先进的蓝牙 Wi Fi USB协议分析仪 支持低功耗蓝牙协议分析测试 支持蓝牙5低功耗以及Wi Fi的物联网应用 支持与原始频谱 UART SPI HCI 逻辑信号等同步的宽带蓝牙5低能耗BLE Wi F
  • [Linux]-进程间通信之消息队列

    目录 消息队列的概述 消息队列的API 1 获取系统唯一Key值 IPC键值 2 创建消息队列 2 1查看消息队列的一些Linux命令 2 2消息队列的创建 3 消息的发送以及定义 3 1 通过消息队列发送信息 4 信息的接收 5 通过消息