IPC 共享内存和 消息队列(发送、接收、移除)以及键值的生成
一、消息对列
消息队列,是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识。
特点:
消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级。消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除。消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取。
原型:
#include <sys/msg.h>// 创建或打开消息队列:成功返回队列ID,失败返回-1,flag是打开队列的方式。int msgget(key_t key, int flag);// 添加消息:成功返回0,失败返回-1,ptr是消息,size是消息的大小,flag是标志位。int msgsnd(int msqid, const void *ptr, size_t size, int flag);// 读取消息:成功返回消息数据的长度,失败返回-1,ptr是消息,size是消息的大小,type是消息的类型,flag是标志位。int msgrcv(int msqid, void *ptr, size_t size, long type,int flag);// 控制消息队列:成功返回0,失败返回-1int msgctl(int msqid, int cmd, struct msqid_ds *buf);
在以下两种情况下,msgget将创建一个新的消息队列:
如果没有与键值key相对应的消息队列,并且flag中包含了IPC_CREAT标志位。
key参数为IPC_PRIVATE。
函数msgrcv在读取消息队列时,type参数有下面几种情况:
type == 0,返回队列中的第一个消息;
type > 0,返回队列中消息类型为 type 的第一个消息;
type < 0,返回队列中消息类型值小于或等于 type 绝对值的消息,如果有多个,则取类型值最小的消息。
可以看出,type值非 0 时用于以非先进先出次序读消息。也可以把 type 看做优先级的权值。(其他的参数解释,请自行Google之)
ftok函数
系统建立IPC通讯 (消息队列、信号量和共享内存) 时必须指定一个ID值。通常情况下,该id值通过ftok函数得到。
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok( const char * fname, int id )
fname就是你指定的文件名(已经存在的文件名),一般使用当前目录,如:
key_t key;
key = ftok(".", 1); 这样就是将fname设为当前目录。
id是子序号。虽然是int类型,但是只使用8bits(1-255)。
在一般的UNIX实现中,是将文件的索引节点号取出,前面加上子序号得到key_t的返回值。
如指定文件的索引节点号为65538,换算成16进制为0x010002,而你指定的ID值为38,换算成16进制为0x26,则最后的key_t返回值为0x26010002。
查询文件索引节点号的方法是: ls -i
当删除重建文件后,索引节点号由操作系统根据当时文件系统的使用情况分配,因此与原来不同,所以得到的索引节点号也不同。
接收代码演示
#include<stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include<string.h>
struct msgbuf
{long mtype; //信息的类型,必须大于0char mtext[128];//信息数据存放
};
int main()
{//1.huoqu duiliekey_t key;key=ftok(".",'z');struct msgbuf readbuf;printf("key =%x\n",key);//%x 是六进制的形式struct msgbuf sendbuf={988,"thank you for reach"};int msgid=msgget(key,IPC_CREAT|0777);//IPC_CREAT|0777分别表示创建队列,和队列的权限
// printf("ID=%x",msgid);if(msgid==-1){printf("creat fail\n");}msgrcv(msgid,&readbuf,sizeof(readbuf.mtext),888,0);// 如果最后一个为0,以默认的方式来读,读不到的话会堵塞msgsnd(msgid,&sendbuf,strlen(sendbuf.mtext),0);printf("read from que:%s\n",readbuf.mtext);msgctl(msgid,IPC_RMID,NULL);return 0;
}
发送代码演示
<sys/msg.h>
#include<string.h>
struct msgbuf
{long mtype;char mtext[128];
};
int main()
{key_t key;key=ftok(".",'z');printf("key =%x\n",key);struct msgbuf sendbuf={888,"this is message from quen"};//888 是消息类型struct msgbuf readbuf;int msgid=msgget(key,IPC_CREAT|0777);if(msgid==-1){printf("creat fail\n");}msgsnd(msgid,&sendbuf,strlen(sendbuf.mtext),0);msgrcv(msgid,&readbuf,sizeof(readbuf.mtext),988,0);printf("return from get:%s\n",readbuf.mtext);msgctl(msgid,IPC_RMID,NULL);//IPC_RMID将消息队列的链表从内核中移除。一般最后一个写NULL,第一个是队列id。return 0;
}
共享内存
共享内存(Shared Memory),指两个或多个进程共享一个给定的存储区。
特点:
共享内存是最快的一种 IPC,因为进程是直接对内存进行存取。因为多个进程可以同时操作,所以需要进行同步。信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问。
思路:
(1)创建共享内存、若已经存在则直接打开
(2)映射将共享内存映射到进程独自的内存空间
(3)数据交换
(4)释放共享内存
(5)干掉共享内存
相关API
#include <sys/shm.h>// 创建或获取一个共享内存:成功返回共享内存ID,失败返回-1,共享内存的大小必须以兆对齐。int shmget(key_t key, size_t size, int flag);// (映射)连接共享内存到当前进程的地址空间:成功返回指向共享内存的指针,失败返回-1void *shmat(int shm_id, const void *addr, int flag);// 断开与共享内存的连接:成功返回0,失败返回-1int shmdt(void *addr); // 控制共享内存的相关信息:成功返回0,失败返回-1int shmctl(int shm_id, int cmd, struct shmid_ds *buf);
当用shmget函数创建一段共享内存时,必须指定其 size;而如果引用一个已存在的共享内存,则将 size 指定为0 。
当一段共享内存被创建以后,它并不能被任何进程访问。必须使用shmat函数连接该共享内存到当前进程的地址空间,连接成功后把共享内存区对象映射到调用进程的地址空间,随后可像本地空间一样访问。
shmdt函数是用来断开shmat建立的连接的。注意,这并不是从系统中删除该共享内存,只是当前进程不能再访问该共享内存而已。
shmctl函数可以对共享内存执行多种操作,根据参数 cmd 执行相应的操作。常用的是IPC_RMID(从系统中删除该共享内存)。
写端代码
#include<stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include<stdlib.h>
#include <string.h>
//int shmget(key_t key, size_t size, int shmflg);
int main()
{int shmid;char* shmaddr;key_t key;key=ftok(".",1);shmaddr=(char*)malloc(1024*4);shmid=shmget(key,1024*4,IPC_CREAT|0666);//IPC_CREAT|0666 创建共享内存,注明内存权限可读可写if(shmid==-1){printf("creat fail\n");exit(-1);// 异常退出返回-1,正常退出返回0.}else{shmaddr=shmat(shmid,0,0);//第二个一般写0,linux内核为我们自动的安排共享内存,第三个写0,表示映射进来的共享内存是可读可写的。printf("shmat ok\n");strcpy(shmaddr,"I am handsome");//将内容写入共享内存sleep(5);shmdt(shmaddr);//将映射的地址放入,卸载共享内存shmctl(shmid,IPC_RMID,0);//第三个参数用来存放卸载共享内存时产生的信息,不关心就写0.IPC_RMID删除共享内存printf("quit\n");}return 0;
}
读端代码
#include<stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include<stdlib.h>
#include <string.h>
//int shmget(key_t key, size_t size, int shmflg);
int main()
{int shmid;char* shmaddr;key_t key;key=ftok(".",1);shmaddr=(char*)malloc(1024*4);shmid=shmget(key,1024*4,0);// 读的时候只获取不创建所以最后的代码写0.if(shmid==-1){printf("creat fail\n");exit(-1);}else{shmaddr=shmat(shmid,0,0);printf("shmat ok\n");printf("data is %s\n",shmaddr);shmdt(shmaddr);printf("quit\n");shmctl(shmid,IPC_RMID,0);}return 0;
}
ipcs -m -------查看系统中有哪些共享内存
ipcrm -m + 共享内存ID号------删除共享内存
IPC 共享内存和 消息队列(发送、接收、移除)以及键值的生成相关推荐
- Linux下进程间通信方式之管道、信号、共享内存、消息队列、信号量、套接字
/* 1,进程间通信 (IPC ) Inter-Process Communication比较好理解概念的就是进程间通信就是在不同进程之间传播或交换信息.2,linux下IPC机制的分类:管道.信号. ...
- 【Linux Program】信号量、共享内存和消息队列
系列文章: 文件操作 数据管理 进程和信号 POSIX 线程 进程间通信:管道 信号量共享内存和消息队列 套接字 文章目录 1. 信号量 1.1 信号量的定义 1.2 Linux 的信号量机制 1.3 ...
- ipcs命令详解——共享内存、消息队列、信号量定位利器【转】
(转自:https://blog.csdn.net/dalongyes/article/details/50616162?utm_medium=distribute.pc_relevant.none- ...
- php 共享内存列队,php中对共享内存,消息队列的操作
消息队列中的数据同样受到大小的约束,具体约束范围可通过msg_stat_queue的msg_qbytes看到.这段代码唯一有点小改动的地方就在接受消息时,指定了MSG_IPC_NOWAIT,不然如果目 ...
- VxWorks中的任务间通信(信号量、共享内存、消息队列、管道、信号、事件、套接字socket)
文章目录 信号量 共享内存 消息队列 管道 信号 事件 套接字(socket) 总结 VxWorks5.5中,为了保证各个独立的任务可以协同工作,提供了一整套任务间的通信机制,主要包括信号量,共享内存 ...
- 《linux程序设计》--读书笔记--第十四章信号量、共享内存和消息队列
信号量:用于管理对资源的访问: 共享内存:用于在程序之间高效的共享数据: 消息队列:在程序之间传递数据的一种简单方法: 一.信号量 临界代码:需要确保只有一个进程或者一个执行线程可以进入这个临界代码并 ...
- Linux 进程间通信:管道、共享内存、消息队列、信号量
进程间通信 管道 共享内存 消息队列 信号量 进程间通信 https://blog.csdn.net/qq_35423154/article/details/105294963 在之前的一篇博客中讲过 ...
- linux 进程间通信及makefile 无名管道/有名管道/共享内存/信号/消息队列
http://www.voidcn.com/article/p-hxvuiypm-mr.html https://www.cnblogs.com/wuyida/archive/2013/02/03/6 ...
- Linux无锁共享内存,优秀数据结构学习 - 共享内存无锁队列的实现(二)
优秀数据结构学习 - 共享内存无锁队列的实现(二) 优秀数据结构学习 - 共享内存无锁队列的实现(二) 1 关键技术 操作系统提供的进程间通信机制有文件.socket.消息队列.管道.共享内存等.其中 ...
最新文章
- Windows 64位下安装Redis详细教程
- iOS开发UI篇—transframe属性(形变)
- CUDA Samples: matrix multiplication(C = A * B)
- 祝福遨游:傲游浏览器3月将入住欧盟Win7用户桌面
- 举例详细说明javascript作用域、闭包原理以及性能问题(转)
- Spring 更好地处理 Struts 动作
- 将Windows8安装在手持终端上
- SDNU 1194.传纸条(DP) 1032.机器人
- 如果误删谷歌浏览器的书签,怎么恢复
- android 控件方向旋转90度,android – 旋转视图层次90度
- cos大乱斗服务器维护,《COS大乱斗》服务器数据互通公告
- Reflector反编译.NET文件后修复
- SQL题目练习---三表联查
- Android Studio 2.0:速度提升,极大提高开发效率
- 转一个PS图像处理技巧大全,很实用!
- 服务器安全证书未生效怎么办,win7打开网页提示“该服务器的安全证书尚未生效...
- VS源文件提取工具vsjuicer 实现细节
- 国有企业内部审计浅议
- OpenLayers基础教程——要素的编辑
- Linux性能调优的优化思路