目录
一:当前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;
}
结果:
发送 消息队列
查看 消息队列 发送成功
接收 消息队列 成功
接收后