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

    http://user:password@hostname:port/absolute-path?query. http:  协议 user:password@   认证 hostname:  主机名 ...

  2. SharePreference是如何实现的——序列化XML文件

    还记得上一篇我们讲到了用SharePreference来存储数据,那么究竟它是如何实现的呢,今天我们就来仔细看看其实现的细节,我们给它一个准确的名字,叫做XML序列化器(XmlSerializer). ...

  3. Android开发笔记——常见BUG类型之内存泄露与线程安全

    本文内容来源于最近一次内部分享的总结,没来得及详细整理,见谅. 本次分享主要对内存泄露和线程安全这两个问题进行一些说明,内部代码扫描发现的BUG大致分为四类:1)空指针:2)除0:3)内存.资源泄露: ...

  4. IOS的UI基础01

    内容大纲:(红色表示博主个人重点记忆) 1.指定启动界面 带箭头就是首次启动的页面2.两个常用的快捷键3.拖线子控件注意事项4.一般情况下,UIView的容器是控制器的View.5.didRecive ...

  5. javascript 构造函数方式定义对象

    javascript是动态语言,可以在运行时给对象添加属性,也可以给对象删除(delete)属性 <html> <head> <script type="tex ...

  6. crontab 例行性排程

    那么我们就来聊一聊 crontab 的语法吧![root@www ~]# crontab [-u username] [-l|-e|-r]选项不参数:-u :只有 root 才能迚行这个仸务,亦即帮其 ...

  7. 通过代码实现gz压缩,并保持原来的文件名

    写这篇博客主要是为了记录一下这两天来的研究成果-gz带原有文件名压缩.首先要说的是这个解决方案不是通过调用命令gzip来做的,而是通过java代码来实现的,其中用到了apache的common com ...

  8. jQuery Form 表单提交插件-----formSerialize,fieldSerialize,fieldValue,resetForm,clearForm,clearFields的 应用

    一.jQuery Form的其他api  1.  formSerialize 将表单序列化成查询串.这个方法将返回一个形如: name1=value1&name2=value2的字符串.是否可 ...

  9. zju 1937 初涉——深度优先搜索

    #include "stdio.h" int a[11],b[11]; int k,flag,n,s; void DFS(); int main() { int i; while( ...

  10. redis状态查看

      https://redis.readthedocs.org/en/latest/server/slowlog.html   https://redis.readthedocs.org/en/lat ...