赞
踩
目录
现在linux使用的进程间通信方式:
1 管道(pipe)和命名管道(FIFO)
2 信号(signal)
3 消息队列【系统管理】
4 共享内存【系统管理】
5 信号量【系统管理】
6 套接字(socket)
socket套接字就是网络,网络编程也是IPC技术
利用网络实现两个应用程序之间的通信 【客户端和服务器】【两个进程间通信】
上面IPC技术中的 1-5都是本机操作,而6是两台计算机操作
消息队列提供了一个 从一个进程向另外一个进程发送一块数据【一块数据 结构体】的方法
每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值
消息队列也有管道一样的不足,就是每个数据块的最大长度是有上限的[结构体有一定大小],系统上全体队列的最大总长度也有一个上限[系统管理着消息队列]
内存三剑客:
消息队列 、 共享内存 、 信号量
Linux操作系统可以通过命令查看 ipcs
消息队列 共享内存 信号量都是由操作系统直接管理的
信号和管道是由代码编写的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”
查看msgget使用说明
返回:
成功(> -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;
- }
-
ipcs查看内存三剑客 可以看到消息队列创建成功
拥有者root 权限777 ,msqid是0 消息是0
将VS关闭程序运行,再次ipcs查看,消息队列的数据还在
说明了消息队列是由操作系统来管理 ,其内存空间也是由操作系统来管理,虽然进程关闭,但是消息队列还在
如果想要删除,使用 ipcrm,通过命令可以删除
ipcrm -h 可以查看 对于内存三剑客的操作
一般采取 ipcrm -a 初始化操作系统内存
根据手册提示 输入命名 ipcrm -q 0【按id号移除消息队列】
ipcs查看操作系统的内存,可以看出原先创建的消息队列已经被成功删除
对共享内存 消息队列 信号量 使用命令 ipcrm -a 来删除 最容易
ipcrm -a 初始化操作系统内存
有些属于操作系统的内存不可被删除,如上图中 那些操作权限600,状态 2 的都是操作系统本身自带的 ,是不允许删除的
可以删除的只能是代码创建的,系统本身的内存是不可以被删除的
msgsnd函数
函数作用:把一条消息添加到消息队列里去
函数原型
int msgsnd(int msgid,const void *msg_ptr,size_t msg_sz,int msgflg);
msgid:由msgget函数返回的消息队列标识码
msg_ptr:是一个指针,指针指向准备发送的消息,
msg_sz:是msg_ptr指向的消息长度,这个长度不能保存消息类型的那个“long int”长整型计算在内
msgflg:控制着当前消息队列满或到达系统上限时将要发生的事情
操作成功,返回“0”,如果失败,则返回“-1”
查看msgsnd使用说明
msgbuf:必须指向固定要求的结构体
并且结构体 消息类型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 查看操作系统内存
查看msgcrv函数使用说明
消息队列的发送与接收,案例实现
发送 进程
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;
- }
-
g++ main.cpp -o main
./main
运行程序 生成进程
消息队列创建成功 发送消息队列
ipcs查看内存
可以看出
消息队列 发送成功
g++ main.cpp -o main
./main
运行程序 生成进程
可以看出
接收 消息队列 成功
接收后 ipcs查看消息队列
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。