【Linux学习】- 消息队列

目录

一:当前IPC技术

二:消息队列

三:消息队列函数

四:了解消息队列 【代码学习

五:msgsnd函数 

六:消息队列的发送和接收【代码学习】


一:当前IPC技术

•现在linux使用的进程间通信方式:
(1)管道(pipe)和命名管道(FIFO)
(2)信号(signal)
(3)消息队列
(4)共享内存
(5)信号量

                  (6)套接字(socket)

套接字就是网络,网络编程也是IPC技术。利用网络实现两个应用程序之间的通信 【客户端和服务器】【两个进程间通信】,1-5都是本机操作,而6是两台计算机操作。

二:消息队列

•消息队列提供了一个从一个进程向另外一个进程发送[一块]数据【一块数据-结构体】的方法
•每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值
•消息队列也有管道一样的不足,就是每个数据块的最大长度是有上限的[结构体有一定大小],系统上全体队列的最大总长度也有一个上限[系统管理着消息队列]

操作系统直接管理的IPC可以查看:

消息队列 共享内存 信号量都是由操作系统直接管理的。 

信号和管道是由代码编写的main函数的主进程来管理的。

由操作系统管理的,那么它的整个内存区域不算做是进程间的。

信号和管道 的 内存区域是在 进程中的 ,消息队列 共享内存和信号量的内存区域在操作系统中【也就是在当前的要通信的两个进程的外部,内存空间不在进程中,不属于任何进程】

消息队列 共享内存和信号量 这三个 不属于任何进程 。

消息队列是消息的链表,存放在内核中并由消息队列标识符表示。

三:消息队列函数

包含头文件:<sys/msg.h><sys/types.h>和<sys/ipc.h>

int msgctl(int msqid, int cmd, struct msqid_ds *buf);//操作【如增删】

int msgget(key_t key, int msgflg);//【创建消息队列】

msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz,   long msg_typ, int msgflg);//接收

msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg);//发送

msgget函数

作用:用来创建和访问一个消息队列

•key: 某个消息队列的名字
•msgflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的
•如果操作成功,msgget将返回一个非负整数,即该消息队列的标识码;如果失败,则返回“-1”

四:了解消息队列 【代码学习】

返回:成功(> -1)返回消息队列ID号/类型, -1则是出错/错误码

main.cpp

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

using namespace std;

int main()
{
	if (msgget((key_t)1001, IPC_CREAT | 0777) == -1)
	{
		perror("msgget error");
	}
	else
	{
		cout << "消息队列创建成功" << endl;
	}
	return 0;
}

可以看到创建成功 拥有者root 权限777 ,id是0 消息是0

将VS关闭程序运行,再次ipcs查看,消息队列数据还在。

说明了消息队列是由操作系统来管理 ,其内存空间也是由操作系统来管理,虽然进程关闭,但是消息队列还在。

如果想要删除,使用 ipcrm,通过命令可以删除

根据手册提示 输入命名 ipcrm -q 0【按id号移除消息队列】

ipcs查看 原先创建的消息队列已经被成功删除

对共享内存 消息队列 信号量 使用命令 ipcrm -a 来删除 最容易 

有些属于操作系统的不会被删除,那些操作权限600,状态 2 的都是操作系统本身自带的 ,不允许删除。可以删除的只能是代码创建的,系统本身的不可被删除。

五:msgsnd函数 

作用:把一条消息添加到消息队列里去

•msgid: 由msgget函数返回的消息队列标识码
•msg_ptr:是一个指针,指针指向准备发送的消息,
•msg_sz:是msg_ptr指向的消息长度,这个长度不能保存消息类型的那个“long int”长整型计算在内
•msgflg:控制着当前消息队列满或到达系统上限时将要发生的事情
•操作成功,返回“0”,如果失败,则返回“-1”

必须指向固定要求的结构体 并且结构体  消息类型long型必须是>0   和  消息数据(char数据类型)

返回值:-1/错误码 是 失败 

main.cpp

#include<iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include<stdio.h>
#include<string.h>

using namespace std;

typedef struct msgsendbuf {
	long mtype;       /* message type, must be > 0 */
	char mtext[50];    /* message data */
}MSGBUF;


int main()
{
    //key_t如果不存在则创建,key_t如果存在则访问
	int msgid = msgget((key_t)1001, IPC_CREAT | 0777);
	if (msgid == -1)
	{
		perror("msgget error");
	}
	else
	{
		cout << "消息队列创建成功" << endl;
	}

	MSGBUF buf;
	buf.mtype = 1;//设置消息类型
	strcpy(buf.mtext, "hello world");

	//发送消息
	if (msgsnd(msgid, &buf, sizeof(MSGBUF), 0) == -1)
	{
		perror("msgsnd error");
	}

	return 0;
}

已用字节数64 消息 1 ,已经发送消息成功。 【VS中运行程序关闭,再ipcs查看,消息队列仍然存在】

若消息队列不删除,再次运行一次程序。

可以看出字节数 128【发送一次64 发送二次128】   消息 2 【发送2次】

对于msgget:key_t如果不存在则创建,key_t如果存在则访问

消息队列顺序 

队列:先进先出

尾部追加 头部删除

六:消息队列的发送和接收【代码学习】

初始化处理消息队列: 

命令 ipcrm -a                   

命令 ipcs

学习接收消息队列


消息队列的发送和接收 代码实现:

发送

main.cpp 

#include<iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include<stdio.h>
#include<string.h>

using namespace std;

typedef struct msgsendbuf {
	long mtype;       /* message type, must be > 0 */
	char mtext[50];    /* message data */
}MSGBUF;


int main()
{
	//key_t如果不存在则创建,key_t如果存在则访问
	int msgid = msgget((key_t)1001, IPC_CREAT | 0777);
	if (msgid == -1)
	{
		perror("msgget error");
	}
	else
	{
		cout << "消息队列创建成功" << endl;
	}

	for (int i = 0; i < 3; i++)
	{
		MSGBUF buf;
		buf.mtype = 1;//设置消息类型
		sprintf(buf.mtext, "hello world %d", i);

		//发送消息
		if (msgsnd(msgid, &buf, sizeof(MSGBUF), 0) == -1)
		{
			perror("msgsnd error");
		}
	}
	return 0;
}

接收

main.cpp

#include<iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include<stdio.h>
#include<string.h>

using namespace std;

typedef struct msgsendbuf {
	long mtype;       /* message type, must be > 0 */
	char mtext[50];    /* message data */
}MSGBUF;


int main()
{
	//key_t如果不存在则创建,key_t如果存在则访问
	int msgid = msgget((key_t)1001, IPC_CREAT | 0777);
	if (msgid == -1)
	{
		perror("msgget error");
	}
	else
	{
		cout << "消息队列创建成功" << endl;
	}

	MSGBUF buf = { 0 };

	for (int i = 0; i < 3; i++)
	{
		if (msgrcv(msgid, &buf, sizeof(MSGBUF), 1, 0) < 0)
		{
			perror("msgrcv error");
		}
		else {
			cout << "buf.mtext = " << buf.mtext << endl;
		}
	}
	return 0;
}

结果:

发送 消息队列

查看 消息队列 发送成功 

接收 消息队列 成功 

接收后 

  

猜你喜欢

转载自blog.csdn.net/m0_56051805/article/details/125792766