共享内存是由内核出于在多个进程间交换信息的目的而留出的一块内存区(段)。
如果段的权限设置恰当,每个要访问该段内存的进程都可以把它映像到自己的私有地址空间中。
如果一个进程更新了段中的数据,其他进程也立即会看到更新。
由一个进程创建的段,也可以由另一个进程读写。
每个进程都把它自己对共享内存的映像放入自己的地址空间。
创建共享内存区
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 进程通信(共享内存区)的更多相关文章

  1. Linux学习笔记(14)-进程通信|共享内存

    在Linux中,共享内存是允许两个不相关的进程访问同一个逻辑内存的进程间通信方法,是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式. 不同进程之间共享的内存通常安排为同一段物理内存.进程可 ...

  2. Windows进程通信 -- 共享内存(1)

    共享内存的方式原理就是将一份物理内存映射到不同进程各自的虚拟地址空间上,这样每个进程都可以读取同一份数据,从而实现进程通信.因为是通过内存操作实现通信,因此是一种最高效的数据交换方法. 共享内存在 W ...

  3. Windows进程通信 -- 共享内存

    享内存的方式原理就是将一份物理内存映射到不同进程各自的虚拟地址空间上,这样每个进程都可以读取同一份数据,从而实现进程通信.因为是通过内存操作实现通信,因此是一种最高效的数据交换方法. 共享内存在 Wi ...

  4. Windows进程通信-共享内存空间

    三个模块 1,game.exe,三个方法,控制台输入指令('A','B','R')分别控制三个方法的调用: 2,WGDll.dll,要注入到game进程中的dll文件: 3,myconsole.exe ...

  5. linux 进程间共享内存示例

    写入端: #include <iostream> #include <unistd.h> #include <stdlib.h> #include <stdi ...

  6. linux 进程通信之 共享内存

    共享内存是被多个进程共享的一部分物理内存.共享内存是进程间共享数据的一种最快的方法.一个进程向共享内存区域写入了数据,共享这个内存区域的全部进程就能够立马看到当中的内容. 关于共享内存使用的API k ...

  7. Linux环境编程之共享内存区(一):共享内存区简单介绍

    共享内存区是可用IPC形式中最快的.一旦内存区映射到共享它的进程的地址空间,进程间数据的传递就不再涉及内核.然而往该共享内存区存放信息或从中取走信息的进程间通常须要某种形式的同步.不再涉及内核是指:进 ...

  8. Posix共享内存区

    1.概述 Posix提供了两种在无亲缘关系进程间共享内存区的方法: (1)内存映射文件:先有open函数打开,然后调用mmap函数把得到的描述符映射到当前进程地址空间中的一个文件(上一篇笔记所用到的就 ...

  9. Linux进程通信之System V共享内存

    前面已经介绍过了POSIX共享内存区,System V共享内存区在概念上类似POSIX共享内存区,POSIX共享内存区的使用是调用shm_open创建共享内存区后调用mmap进行内存区的映射,而Sys ...

随机推荐

  1. org.apache.http.conn.HttpHostConnectException: Connection to http://localhost refused in android

    给Manifest加网络权限<uses-permission android:name="android.permission.INTERNET"/>

  2. 读取本地Json文件

    //读取Json文件  地区 //将文件拖到本地  获取json数据 //获取json文件路径 NSString *pathArea=[[NSBundle mainBundle] pathForRes ...

  3. Swift学习--常量.变量.数据类型的使用(一)

    一.Swift中的常量和变量 /* Swift 中定义常量和变量用let/var let 代表定义一个常量 var 代表定义一个变量 Swift 中代表定义常量和变量不需要写数据类型,编译器辉根据我们 ...

  4. [docker] 管理docker容器中的数据

    之前我们介绍了Docker的基本概念(前面的没翻译...),了解了如何使用Docker镜像进行工作,并且学习了网 络和容器之间的链接.这一节我们将讨论如何管理容器中及容器之间的数据. 我们将查看下面两 ...

  5. python arguments *args and **args ** is for dictionaries, * is for lists or tuples.

    below is a good answer for this question , so I copy on here for some people need it By the way, the ...

  6. INFORMATICA 的调优之 INFORMATICA SERVER TUNING

    INFORMATICA SERVER的调优我认为主要从两个级别来做,一个是MAPPING级别,一个是SESSION级别. 对于MAPPING级别的调优: 一  对MAPPING数据流向的优化: 1 控 ...

  7. 用python自定义实现db2的连接池

    想要模仿zabbix的oracle插件orabix来实现对db2的监控,但是Java能力有限,就用python来实现了.但是python常用的连接池PooledDB似乎并不支持db2,一直报这样的错误 ...

  8. lucene入门

    一.lucene简介 Lucene是apache下的一个靠性能的.功能全面的用纯java开发的一个全文搜索引擎库.它几乎适合任何需要全文搜索应用程序,尤其是跨平台.lucene是开源的免费的工程.lu ...

  9. jQuery Form 表单提交插件-----ajaxForm() 的应用

    Form Plugin API 里提供了很多有用的方法可以让你轻松的处理表单里的数据和表单的提交过程. 测试环境:部署到Tomcat中的web项目. 一.ajaxForm() 介绍  ajaxForm ...

  10. 解决在iOS8环境下,当用户关闭定位服务总开关时,无法将APP定位子选项加入定位权限列表的问题

    关键点:- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizati ...