Linux 进程通信(共享内存区)
共享内存是由内核出于在多个进程间交换信息的目的而留出的一块内存区(段)。
如果段的权限设置恰当,每个要访问该段内存的进程都可以把它映像到自己的私有地址空间中。
如果一个进程更新了段中的数据,其他进程也立即会看到更新。
由一个进程创建的段,也可以由另一个进程读写。
每个进程都把它自己对共享内存的映像放入自己的地址空间。
创建共享内存区
int shmget(key_t key,size_t size,int shm-flg);
参数key既可以是IPC_PRIVATE(IPC_PRIVATE表示让系统分配一个Key),也可以是ftok函数返回的一个关键字。
参数size指定段的大小。
参数flgs--八进制数,,转化为二进制后分别代表rw-rw-rw-
shmget成功返回段标识符,失败返回-(一般不会创建失败,除非系统没有内存).
注意:只有创建权限是0666的才可以用命令行"ipcs -m"查看,其他类型权限的共享内存区无法被这个命令所查看。
//创建共享内存
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h> #include <sys/ipc.h>
#include <sys/shm.h> int main(int arg, char *args[])
{
int shmid=shmget(IPC_PRIVATE,sizeof(char)*,);
if(shmid==-)
{
printf("error\n");
return -;
}
printf("创建共享内存成功!内存段标识符是%d\n",shmid);
return ;
}
在命令行执行"ipcs -m "显示已经成功的创建了一块共享内存区。
nattch字段显示已经附加到这个内存区的进程数。
附加共享内存区
void * shmat(int shmid,void * shmaddr,int shmflg);
int shmdt(const * void shmaddr);
参数shmid是要附加的共享内存区标识符(在命令行执行ipcs -m 显示)。
总是把参数shmaddr设为0,0表示系统会自动在被附加的进程内创建一个内存段,映射到共享内存区。当然也可以指定一个被附加的进程内的一块内存,但是需要用户自己malloc分配内存,并将地址传给shmaddr参数,比较麻烦,一般使用系统自动分配。
参数shmflg可以为SHM_RDONLY,这意味着附加段是只读的,参数为0时,表示可以读写。
shmat成功返回被附加了段的地址,失败返回-,并设置errno,虽然返回值是指针类型,但是返回的的确是-1。
函数shmdt是将附加在shmaddr的段从调用进程的地址空间分离出去,这个地址必须是shmat返回的(即从自己进程内释放被附加的共享内存,强调不是释放系统的那个共享内存)。
注意:进程里附加共享内存区的大小一定是和系统共享内存一样大,为了方便映射(两块内存不一样大如何同步数据?)。
//创建附加共享内存
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h> #include <sys/types.h>
#include <sys/shm.h> int main(int arg, char *args[])
{
if (arg < )
{
printf("请输入2个参数!\n");
return -;
}
int flag = ;
int shmid = ;
shmid = atoi(args[]);
flag = atoi(args[]);
//创建本进程被附加的共享内存
void * shmbuf = NULL;
shmbuf = shmat(shmid, , );
/*
编译警告:warning: cast from pointer to integer of different size
这句警告意思是指针类型大小和Int类型大小不同,根据以前的知识,指针都是4个字节大小,
其实指针的大小不是固定的4个字节。32位cpu的计算机上是4字节,64位cpu的计算机上是8个字节。
这是因为32位计算机中的地址是32位的(可以在32位系统下查看指针的值例如--0x003bf9a3)
但是在64位计算机中地址是64位的(可以在64位系统下查看指针的值例如--0xffffffffffffffff)
十六进制数字的1位等于二进制的4位
虽然指针的值在32位系统和64位系统中有区别,但是一个字节的大小在两个系统中是相同的,
举例说Int类型数据,不管是在32位系统和64位系统中都在内存中占据4个字节大小的内存空间
*/
if ((int) shmbuf == -)
{
printf("创建附加共享内存区失败!error message:%s\n", strerror(errno));
return -;
}
sleep();
if (flag == )
{
//将数据写入本进程自己的附加共享内存区
//这里系统共享内存区的大小是1kb
read(STDIN_FILENO, shmbuf, sizeof(char) * );
} else if (flag == )
{
printf("%s", shmbuf);
}
return ;
}
shmdt函数
--功能:将共享内存段与当前进程脱离
--参数
shmarr:由shmat所返回的指针
--返回值:成功返回0,失败返回-
--注意:将共享内存段与当前进程脱离不等于删除共享内存
释放共享内存区
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
参数shmid是共享内存区段标识符,
参数cmd一般有三个值IPC_STAT(获取共享内存区的状态,由第三个参数获取状态),IPC_SET(设置共享内存区),IPC_RMID(删除共享内存区,此时第三个参数一般传0);
shmctl成功返回0,失败返回-,并且设置errno的值
//创建共享内存区
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h> int main(int arg,char * args[])
{
if(arg<)
{
printf("请输入一个参数!\n");
return -;
}
int shmid=atoi(args[]);
int flag=shmctl(shmid,IPC_RMID,);
if(flag<)
{
printf("error message:%s\n",strerror(errno));
return -;
}
printf("返回值是%d\n",flag);
return ;
}
命令行释放共享内存区
在命令行执行"ipcrm -m shmid" 或者 "ipcrm shm shmid"
Linux 进程通信(共享内存区)的更多相关文章
- Linux学习笔记(14)-进程通信|共享内存
在Linux中,共享内存是允许两个不相关的进程访问同一个逻辑内存的进程间通信方法,是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式. 不同进程之间共享的内存通常安排为同一段物理内存.进程可 ...
- Windows进程通信 -- 共享内存(1)
共享内存的方式原理就是将一份物理内存映射到不同进程各自的虚拟地址空间上,这样每个进程都可以读取同一份数据,从而实现进程通信.因为是通过内存操作实现通信,因此是一种最高效的数据交换方法. 共享内存在 W ...
- Windows进程通信 -- 共享内存
享内存的方式原理就是将一份物理内存映射到不同进程各自的虚拟地址空间上,这样每个进程都可以读取同一份数据,从而实现进程通信.因为是通过内存操作实现通信,因此是一种最高效的数据交换方法. 共享内存在 Wi ...
- Windows进程通信-共享内存空间
三个模块 1,game.exe,三个方法,控制台输入指令('A','B','R')分别控制三个方法的调用: 2,WGDll.dll,要注入到game进程中的dll文件: 3,myconsole.exe ...
- linux 进程间共享内存示例
写入端: #include <iostream> #include <unistd.h> #include <stdlib.h> #include <stdi ...
- linux 进程通信之 共享内存
共享内存是被多个进程共享的一部分物理内存.共享内存是进程间共享数据的一种最快的方法.一个进程向共享内存区域写入了数据,共享这个内存区域的全部进程就能够立马看到当中的内容. 关于共享内存使用的API k ...
- Linux环境编程之共享内存区(一):共享内存区简单介绍
共享内存区是可用IPC形式中最快的.一旦内存区映射到共享它的进程的地址空间,进程间数据的传递就不再涉及内核.然而往该共享内存区存放信息或从中取走信息的进程间通常须要某种形式的同步.不再涉及内核是指:进 ...
- Posix共享内存区
1.概述 Posix提供了两种在无亲缘关系进程间共享内存区的方法: (1)内存映射文件:先有open函数打开,然后调用mmap函数把得到的描述符映射到当前进程地址空间中的一个文件(上一篇笔记所用到的就 ...
- Linux进程通信之System V共享内存
前面已经介绍过了POSIX共享内存区,System V共享内存区在概念上类似POSIX共享内存区,POSIX共享内存区的使用是调用shm_open创建共享内存区后调用mmap进行内存区的映射,而Sys ...
随机推荐
- arc下内存泄漏的解决小技巧
一定要注意,我们运行app时,一定要关心内存的使用,尽量不要超过20M,即使有很多图片要显示也绝对不能超过30M.所以运行自己开发的app时多关心内存的使用是个很好的习惯. 对于性能,内存的优化,这个 ...
- 数位类统计问题--数位DP
有一类与数位有关的区间统计问题.这类问题往往具有比较浓厚的数学味道,无法暴力求解,需要在数位上进行递推等操作.这类问题往往需要一些预处理,这就用到了数位DP. 本文地址:http://www.cnbl ...
- Android 之 json数据的解析(jsonReader)
json数据的解析相对而言,还是比较容易的,实现的代码也十分简单.这里用的是jsonReade方法来进行json数据解析. 1.在解析之前,大家需要知道什么是json数据. json数据存储的对象是无 ...
- android 进程间通信数据(二)------parcel的实现
Serialize是java原生就自带的东西,我们可以看到android的源码 所以看看android是如何实现parcel的,这对我们自己代码设计有什么启发. Parcel: 在android中,p ...
- 解决tomcat6部署spring4+mybatisJSP页面产生的500错误,控制台报java.lang.NullPointerException的问题
搭建spring4+mybatis+springMVC访问项目时产生异常: 严重: Servlet.service() for servlet jsp threw exception java.lan ...
- SAM4E单片机之旅——18、通过AFEC(ADC)获取输入的电压
很多时候,一个电压不仅仅需要定性(高电平或者低电平),而且要定量(了解具体电压的数值).这个时候就可以用到模数转换器(ADC)了.这次的内容是测量开发板搭载的滑动变阻器(VR1)的电压,然后把ADC转 ...
- 读书笔记——Windows核心编程(15)在应用程序中使用虚拟内存
微软的Windows提供了三种机制对内存进行操控 1 虚拟内存(最适合管理大型对象数组或大型结构数组) 2 内存映射文件(大型数据流/文件,共享数据) 3 堆(大量的小型对象) 预订地址空间区域Vi ...
- 使用NDK c++建立一个Android应用
使用NDK c++建立一个Android应用 一.工具 ADT(集成了eclipse,cdt,ndk plug-in) NDK (用它来编译c/c++程序) JDK (Java开发包) ANT(ecl ...
- Python基本语法初试
编程环境: win7旗舰版 Python 3.2.2(default, Sep 4 2011,09:51:08) 代码来源:(Python菜鸟) 代码内容: Python基本的输出语句print(& ...
- 10个值得深思的PHP面试问题
本文所罗列的问题虽然看似简单,但是每个背后都涵盖了一个或几个大家容易忽视的基础知识点,希望能够帮助到你的面试和平时工作. Q1 第一个问题关于弱类型 $str1 = 'yabadabadoo'; $s ...