进程间通信之消息队列

news2024/11/15 19:46:30

消息队列

  • 一. 什么是消息队列
  • 二. 消息队列有关函数
    • 1.获取key - ftok
    • 2.创建消息队列 - msgget
    • 3.发送消息 - msgsnd
    • 4.接收消息 - msgrcv
    • 5.删除消息队列 - msgctl
  • 三. 实例
    • 注意:

一. 什么是消息队列

消息队列独立于发送消息的进程和接收消息的进程,消息队列是消息的链表,存放在内核中并由消息队列标识符标识。
每个消息队列都有一个标识,只有持有这个标识的进程才可以去里面拿消息

生命周期随内核,消息队列会一直存在,需要我们调用接口删除或使用命令删除

在这里插入图片描述

二. 消息队列有关函数

1.获取key - ftok

功能 : 获取一个独一无二的key,作为传给共享内存的一个参数

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

key_t ftok(const char *pathname, int proj_id);
key_t key = ftok("./read", 'a');
pathname:
		提前创建的可访问文件的文件名,可以随意写
proj_id:
		任意一个字符

返回值:
		成功则返回生成的key值,失败则返回-1

2.创建消息队列 - msgget

功能 : 创建消息队列

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

int msgget(key_t key, int msgflg);
int msgget(key_t key,int msgf1g);
key:
		ftok得到的key值或者IPC_PRIVATE(创建私有的消息队列)
msgf1g:
		IPC_CREAT | 0664
返回值:
		成功: 返回消息队列id
		失败: 返回-1;

3.发送消息 - msgsnd

功能 : 发送消息

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

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
int msgsnd(int msqid,const void *msgp,size_t msgsz,int msgf1g);
smqid:
		创建或者打开消息队列得到的id号
msgp:
		是一个结构体指针,类型为struct msgbuf *,表示为发送消息结构体的首地址
		struct msgbuf {
               long mtype;       /* message type, must be > 0 */     类型
               char mtext[1];    /* message data */          	  	 数据
        };

msgsz:
		消息正文内容的大小
msgf1g:
		0:阻塞方式发送
		IPC_NOWAIT:以非阻塞方式发送
返回值:	
		成功:0
		失败:-1

例如:

typedef struct msgbuf//定义消息结构体
{
	1ong mtype;
	char mtext[1024];
}MSG;
#define LEN (sizeof(MSG)-sizeof(long)) 		//计算消息正文内容大小

MSG msg;	//定义消息结构体变量

while(1)
{
	msg.mtype = 100;	//封装消息类型
	fgets(msg.mtext,1024,stdin);	//输入消息正文
	msg.mtext[str1en(msg.mtext)-1] = '\O';
	msgsnd(id,&msg,LEN,O);	//发送消息
}

4.接收消息 - msgrcv

功能 : 接收数据

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

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

msgid:
		创建或者打开消息队列得到的id号
msgp: 
		发送消息结构体的首地址
msgsz:
		消息正文的长度 sizeof(msg) - sizeof(long)
msgtyp:
		消息的类型
msgflg:
		0:阻塞方式发送
		IPC_NOWAIT:以非阻塞方式发送
返回值:	
		成功:0
		失败:-1

5.删除消息队列 - msgctl

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

int msgctl(int msqid, int cmd, struct msqid_ds *buf);
int msgct1(int msgid, int cmd,struct msqid_ds *buf);功能:控制函数
参数:
msgid: 
		创建或者打开消息队列得到的id号
cmd: 
		IPC_STAT:获取消息队列信息,将信息存储在第三个参数地址当中
        IPC_SET:设置消息队列,将第三个参数的地址的消息队列内容,设置到内核消息队列当中
        IPC_RMID:删除消息队列
buf: 
		如果第二个参数为 IPC_RMID,该值可以为NULL
返回值:
		成功: 0
		失败: -1

三. 实例

子进程发送消息,父进程接收消息
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#include <sys/wait.h>

struct msgbuf{
    long mtype;
    char mtext[50];
};

int main(int argc, char *argv[])
{ 
    //1.获取key
    key_t key = ftok("/",'a');
    if(key == -1)
    {
        perror("ftok");
        return -1;
    }

    //2.创建消息队列
    int msgid = msgget(key,IPC_CREAT | 0664);
    if(msgid == -1)
    {
        perror("msgget");
        return -1;
    }

    // 进程间通信
    pid_t pid = fork();
    if(pid < 0)
    {
        perror("fork");
        //如果创建进程失败,删除消息队列
        goto xxx;
    }
    else if(pid == 0)
    {
        struct msgbuf buf;
        while(1)
        {
            /******发送消息******/
            //初始化结构体
            buf.mtype = 10;
            gets(buf.mtext);
            msgsnd(msgid,&buf,sizeof(buf) - sizeof(long),0);
        }
    }
    else
    {
        struct msgbuf buf;
        /******收消息******/
        while(1)
        {
            msgrcv(msgid,&buf,sizeof(buf) - sizeof(long),10,0);
            printf("massge: %s\n",buf.mtext);
            memset(buf.mtext,0,sizeof(buf.mtext));
        }
    }

    //删除消息队列
    int ret = msgctl(msgid, IPC_RMID, NULL);
    if(ret == -1)
    {
        perror("msgctl");
        goto xxx;
    }

xxx:
    sleep(2);
    char str[100] = {0};
    //使用命令删除消息队列
    sprintf(str, "ipcrm -q %d", msgid);
    system(str);
    system("ipcs -q");
    return 0;
} 

注意:

	ipcs -q:      	   //查询显示当前系统的消息队列
	ipcrm -q msgid:     //删除某个消息队列

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/410833.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【牛客刷题专栏】0x19:JZ18 删除链表的节点(C语言编程题)

前言 个人推荐在牛客网刷题(点击可以跳转)&#xff0c;它登陆后会保存刷题记录进度&#xff0c;重新登录时写过的题目代码不会丢失。个人刷题练习系列专栏&#xff1a;个人CSDN牛客刷题专栏。 题目来自&#xff1a;牛客/题库 / 在线编程 / 剑指offer&#xff1a; 目录前言问题…

GPT-5年底上线?初创公司Runway CEO再爆料:OpenAI员工相信GPT-5有望成AGI

来源: 新智源 微信号&#xff1a;AI-era 最近&#xff0c;Runway CEO关于GPT-5的爆料&#xff0c;又被网友们翻了出来&#xff0c;讨论得热火朝天。不论AGI会在哪一年出现&#xff0c;显然&#xff0c;能见证这一天的人都是幸运的。 最近&#xff0c;又有网友翻出了关于GPT-5的…

初识Linux+Linux基本指令(一)

目录 一.&#x1f606;计算机与操作系统&#x1f606; 计算机与操作系统发展史简介: 计算机与操作系统的关系: 二.&#x1f604;Linux操作系统&#x1f604; 开源软件的代名词:Linux 非图形化界面的Liunx 三.&#x1f606;Linux基本指令之文件管理篇&#x1f606; 1.操…

Spring配置数据源

Spring配置数据源数据源的作用环境准备手动创建c3p0数据源封装抽取关键信息&#xff0c;手动创建c3p0数据源使用Spring容器配置数据源数据源的作用 数据源(连接池)是提高程序性能如出现的 事先实例化数据源&#xff0c;初始化部分连接资源 使用连接资源时从数据源中获取 使用完…

网络安全行业现在好混吗,工资水平怎么样?

前段时间看到有人私信&#xff1a;网络安全行业现在好混吗&#xff0c;工资水平怎么样&#xff1f;今天在这里做个回答&#xff0c;不知你所说的“好混吗”指的是什么&#xff1f; 薪资高&#xff0c;待遇好&#xff1f;不加班&#xff0c;活儿少&#xff1f;不受气&#xff0…

我的创作纪念日 - 2048

2048 ✌️ 今天是 2023 年 4 月 10 日&#xff0c;系统说我在 2017 年 08 月 31 日那天发布了第一篇博客&#xff08;【算法】编写一个能将给定非负整数列表中的数字排列成最大数字的程序&#xff09;&#xff0c;距离当时已经有 2048 天了&#xff0c;2048 这个数字真的很能挑…

短期突击面试攻略,收offer如砍瓜切菜!!!

​​​​​现在的面试是什么样的&#xff1f; 面试官拿到简历后会先看下你的技术栈&#xff0c;他面试你的问题就来自这些技术栈 面试官都是看人下菜碟&#xff0c;每次面试问的问题都不一样&#xff0c;会根据你回答问题的情况来决定深入的程度&#xff0c;直到了解清楚你的…

△形网络和Y型网络的变换

△形网络和Y型网络的变换 △形网络也称三角形网络&#xff0c;Y也称星形网络 我们今天就来看下这两种网络是如何变换的。 看下面的电路 如何通过计算得出电流表的读数&#xff1f; 显然电路的串并联结构并不是那么纯粹&#xff0c;Ra Rb Rc构成了一个 △形网络,如下图所示。…

小学数学题升维思考,降维打击

目录一、背景二、题目三、过程1.形式转换2.个位数相加只能向前进一位嘛&#xff1f;3.十位数上要填写的内容?4.如何下意识的去做结构化&#xff1f;四、总结五、升华一、背景 公司的产品是做K12的教育平台&#xff0c;马老板也受感染研究起了小学数学题。一道二年级的题让我窥…

Java阶段一Day19

Java阶段一Day19 文章目录Java阶段一Day19对象流字符流WriterReader转换流缓冲字符流BufferedWriter与PrintWriterBufferedReader异常Throwable、Error、Exception异常处理机制throwthrowstry-catchfinally面试题教师总结新单词JAVA IO对象流对象输入流构造器方法例transient关…

求根号n下界

目录 求根号n 程序设计 程序分析 求根号n 【问题描述】设计一个计算的算法,n是任意正整数。 除了赋值和比较运算,该算法只能用到基本的四则运算操作。 【输入形式】输入一个正整数 【输出形式】输出答案 【样例输入】10 【样例输出】3 【样例说明】表示对n开平方后向…

Linux线程基础:控制和封装

本节重点&#xff1a; 1. 了解线程概念&#xff0c;理解线程与进程区别与联系。 2. 学会线程控制&#xff0c;线程创建&#xff0c;线程终止&#xff0c;线程等待。 3. 了解线程分离与线程安全概念。 Linux线程概念 在一个程序里的一个执行路线就叫做线程&#xff08;threa…

机器学习 00 归一化/标准化

目录 一、归一化/标准化 1.1 为什么我们要进行归一化/标准化? 二、归一化 2.1 定义 2.2 公式 2.3 归一化总结 三、标准化 3.1 定义 3.2 公式 3.3 标准化总结 一、归一化/标准化 1.1 为什么我们要进行归一化/标准化? 特征的单位或者大小相差较大&#xff0c;或者某…

我的软件研发套路

春节回来之后&#xff0c;调整到一个新的团队工作。 团队&#xff0c;是已有的&#xff1b;所用的技术栈&#xff0c;不熟悉&#xff1b;所做的业务领域&#xff0c;也涉猎甚少。挑战比较大。 管理层对团队的产出不满。我的首要任务&#xff0c;是提升团队的效能。 目前团队…

左中右 三栏式 布局

一、中间 自适应&#xff0c;左右两边 宽度固定 方法1&#xff1a;box容器 Flex布局&#xff0c;center设置为 flex:1 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible&q…

神经网络/深度学习(一)

感知机 多层感知机&#xff08;神经网络&#xff09; 误差逆传播&#xff08;error BackPropagation&#xff0c;简称BP&#xff09;算法 深度学习 卷积神经网络&#xff08;Convolutional Neural Networks, CNN&#xff09; 递归&#xff08;循环&#xff09;神经网络&#xf…

sonar覆盖率、代码覆盖率、分支覆盖率的计算方式

代码质量的覆盖率分为三种&#xff0c;覆盖率、代码覆盖率、分支覆盖率&#xff0c;那每一种的计算方式是怎么样的呢&#xff1f; 举例&#xff1a; 上面最有疑惑的是覆盖率&#xff0c;不知道怎么算出了来的&#xff0c;后面再说。 通过sonarqube可以分析出&#xff1a; 指标…

232:vue+openlayers选择左右两部分的地图,不重复,横向卷帘

第232个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+openlayers项目中自定义js实现横向卷帘。这个示例中从左右两个选择框中来选择不同的地图,做了不重复的处理,即同一个数组,两部分根据选择后的状态做disabled处理,避免重复选择。 直接复制下面的 vue+openlayers…

springmvc入门和两个配置类放置时的问题

springmvc 替换之前的servlet&#xff0c;用注解型标记进行操作的servlet类&#xff08;就是之前servlet类上面的Webservlet注解中参数&#xff1a;当前类的访问路径名&#xff09;&#xff0c;然后响应也用注解&#xff0c;据体如下&#xff1a; 先创建web项目 再导入需要的包…

边学边记——Java数据结构☞树和二叉树

目录 一.树 1.定义 2.一些基本概念 3.树的表示形式 二.二叉树 1.概念 2.两种特殊的二叉树 3.二叉树的性质 4.二叉树的存储 5.二叉树的遍历&#xff08;The traversal of A binary Tree&#xff09; 一.树 1.定义 树是一种非线性的数据结构&#xff0c;它是由n&#x…