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号------删除共享内存

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

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

相关文章

DBA十大必备工具(SQLServer)

曾经和一些DBA和数据库开发人员交流时&#xff0c;问他们都用过一些什么样的DB方面的工具&#xff0c;大部分人除了SSMS和Profile之外&#xff0c;基本就没有使用过其他工具了&#xff1b;诚然&#xff0c;SSMS和Profile足够强大&#xff0c;工作的大部分内容都能通过它们搞定&…

linux 信号和信号量编程

对于 Linux来说&#xff0c;实际信号是软中断&#xff0c;许多重要的程序都需要处理信号。信号&#xff0c;为 Linux 提供了一种处理异步事件的方法。比如&#xff0c;终端用户输入了 ctrlc 来中断程序&#xff0c;会通过信号机制停止一个程序。 信号概述 信号的名字和编号&…

安卓动画基础讲解

//逐帧动画 /** * 1.加入单张图片 * 2.生成movie.xml整个图片 * 3.代码中使用图片movie.xml */ iv(ImageView) findViewById(R.id.iv);// iv.setImageResource(R.drawable.movie);//为iv加载六张图片// AnimationDrawable ad(AnimationDrawable) iv.getDrawable();//得到图片给…

JS一些常用的类库

一、返回上一页&#xff08;history&#xff09;发觉有两种用法&#xff1a;1、javascript:history.back(-1);2、javascript:history.go(-1);它们俩的区别是&#xff1a;history.back(-1):直接返回当前页的上一页&#xff0c;数据全部消息&#xff0c;返回新页面history.go(-1)…

Linux上线程开发API概要(线程)

进程与线程 典型的UNIX/Linux进程可以看成只有一个控制线程&#xff1a;一个进程在同一时刻只做一件事情。有了多个控制线程后&#xff0c;在程序设计时可以把进程设计成在同一时刻做不止一件事&#xff0c;每个线程各自处理独立的任务。 进程是程序执行时的一个实例&…

Redis学习笔记1-Redis数据类型

Redis数据类型 Redis支持5种数据类型&#xff0c;它们描述如下&#xff1a; Strings - 字符串 字符串是 Redis 最基本的数据类型。Redis 字符串是二进制安全的&#xff0c;也就是说&#xff0c;一个 Redis 字符串可以包含任意类型的数据&#xff0c;一个字符串最大为 512M 字节…

30个非常有趣的404错误页面设计欣赏

当用户访问一个不存在的页面的时候就会出现404错误页面&#xff0c;这对用户来说是很不友好的。所以很多网站都会去设计一个新颖的错误页面&#xff0c;以吸引用户继续浏览其它的网页内容。今天这篇文章就收集了30个非常有趣的404错误页面设计欣赏&#xff0c;希望能带给你灵感…

线程同步之互斥量加锁解锁 死锁

与互斥锁相关API 互斥量&#xff08;mutex&#xff09;从本质上来说是一把锁&#xff0c;在访问共享资源前对互斥量进行加锁&#xff0c;在访问完成后释放互斥量上的锁。对互斥量进行加锁后&#xff0c;任何其他试图再次对互斥量加锁的线程将会被阻塞直到当前线程释放该互…

游戏开发-从零开始 002

个人开发者的游戏大部分需要完成的内容&#xff1a; 1.完整的游戏玩法逻辑&#xff08;核心&#xff09; 2.UI 3.游戏关卡设计 4.游戏旁白 5.交互细节 6.游戏分享接口 7.游戏道具 8.游戏排行榜&#xff0c;游戏社区&#xff0c;如 GameCenter 9.游戏内购 如 remove Ads 10.广告…

5 个最佳的 Linux 桌面环境

打算把每个桌面都试用一遍&#xff0c;但是那很费时间&#xff0c;而且确实有很多桌面环境可供选择&#xff0c;这就是我发表“最优秀的 Linux 桌面以及他们的优缺点”的目的&#xff0c;本文告诉你在选择桌面时需要注意些什么&#xff0c;让我们开始吧。1. KDE我想从第五个说起…

线程条件控制实现线程的同步

与条件变量相关API 条件变量是线程另一可用的同步机制。条件变量给多个线程提供了一个会合的场所。条件变量与互斥量一起使用时&#xff0c;允许线程以无竞争的方式等待特定的条件发生。 条件本身是由互斥量保护的。线程在改变条件状态前必须首先锁住互斥量&#xff0c…

自定义能够for each的类,C#,Java,C++,C++/cli的实现方法

自定义类能够被for each&#xff0c;应该算是个老生常谈的话题了&#xff0c;相关的资料都很多&#xff0c;不过这里整理总结主流语言的不同实现方式&#xff0c;并比较部分细节上的差异。 第一种语言&#xff0c;也是实现起来最简单的Java语言。在Java里&#xff0c;要被for e…

SQL Server 2008 R2:快速清除日志文件的方法

本例&#xff0c;快速清理“students”数据库的日志&#xff0c;清理后日志文件不足1M。USE [master] GO ALTER DATABASE students SET RECOVERY SIMPLE WITH NO_WAIT GO ALTER DATABASE students SET RECOVERY SIMPLE GO USE students GO--此处需要注意&#xff…

linux网络编程之字节序

进程间通信 特点&#xff1a;依赖于内核&#xff0c;造成缺陷——无法实现多机通信。 网络编程 地址&#xff1a;由IP地址和端口号构成&#xff0c;端口号用来判断客户端接入哪个服务器。 数据的交流&#xff1a;涉及到协议&#xff08;http&#xff0c;tcp&#xff0c;udp&…

Oracle查看表空间和表空间中的对象

select * from user_tables;--查询所有用户表 select username,default_tablespace from user_users;--查询当前表空间select tablespace_name from dba_tablespaces;--查询所有表空间select tablespace_name, sum(bytes)/1024/1024 from dba_data_files group by tablespace_n…

C#中DateTime.Ticks属性及Unix时间戳转换

DateTime.Ticks&#xff1a;表示0001 年 1 月 1 日午夜 12:00:00 以来所经历的 100 纳秒数&#xff0c;即Ticks的属性为100纳秒&#xff08;1Ticks 0.0001毫秒&#xff09;。Unix时间戳&#xff1a;是从1970年1月1日&#xff08;UTC/GMT的午夜&#xff09;开始所经过的秒数&am…

WebBrowser控件的常用方法、属性和事件

1. 属性属性说明Application如果该对象有效&#xff0c;则返回掌管WebBrowser控件的应用程序实现的自动化对象(IDispatch)。如果在宿主对象中自动化对象无效&#xff0c;这个程序将返回WebBrowser 控件的自动化对象Parent返回WebBrowser控件的父自动化对象&#xff0c;通常是一…

二维码高亮

// 二维码高亮。http://blog.sina.com.cn/s/blog_a843a8850102uy6w.html 转载于:https://www.cnblogs.com/muyushifang07/p/5114667.html

socket 网络 编程

网络编程场景 自己是客户端站在5栋楼前&#xff0c;自己要找到5栋楼中的一座并进入某一间房间&#xff0c;这时第二座楼上有人在用汉语&#xff08;tcp/udp&#xff09;说话,我的ip地址&#xff08;楼号&#xff09;是…&#xff0c;我的端口号&#xff08;房间号&#xff09;是…

7个免费的Linux FTP客户端工具

在Dropbox、YouSendIt、idrive以及许多这样云存储和共享工具的帮助下&#xff0c;我们在互联网上发送和共享大型文件变得容易起来。所有这些网站都可以帮助你在互联网上传送文件&#xff0c;但如果你要分享庞大的数据&#xff0c;这依然是很复杂的事情。所以&#xff0c;你需要…