共享内存之——system V共享内存
System V 的IPC对象有共享内存、消息队列、信号灯(量)。
注意:在IPC的通信模式下,不管是共享内存、消息队列还是信号灯,每个IPC的对象都有唯一的名字,称为"键(key)"。通过"键",进程能够识别所用的对象。"键"与IPC对象的关系就如同文件名称于文件,通过文件名,进程能够读写文件内的数据,甚至多个进程能够公用一个文件。而在IPC的通信模式下,通过"键"的使用也能使得一个IPC对象能为多个进程所共用。
一、System V共享内存机制:
system V IPC 机制下的共享内存本质是一段特殊的内存区域,进程间需要共享的数据被放在该共享内存区域中,所有需要访问该共享区域的进程都要把该共享区域映射到本进程的地址空间中去。共享内存允许一个或多个进程通过同时出现在他们的虚拟地址空间的内存进行通信,而这块虚拟内存的页面被每个共享进程的页表条目所引用,同时并不需要再所有进程的虚拟内存都有相同的地址。
1.System V共享内存是一种最为搞笑的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝。
2.为了在多个进程间交换信息,内核专门留出了一块内存区,可以由需要访问的进程将其映射到自己的私有地址空间。进程就可以直接读写这一块内存而不要进行数据的拷贝,从而大大提高效率。
3.由于多个进程共享一段内存,因此也需要依靠某种同步机制。
二、共享内存的操作流程
1. 创建/打开共享内存
2.映射共享内存,即把指定的共享内存映射到进程的地址空间用于访问
3.撤销共享内存的映射
4.删除共享内存对象
三、相关API
step.1----------------->获取一块共享内存
#include<sys/ipc.h>
#include<sys/shm.h> int shmget(key_t key, size_t size, int shmflg)
返回值:调用成功返回一个shmid(类似打开一个或创建一个文件获得的文件描述符一样);
调用失败返回-1;
参数说明:
(1)key:
这两种方式分配的共享内存,一般用来亲缘关系的进程间通信:
当key取值为IPC_PRIVATE,则函数shmget()将创建一块新的共享内存;
当key取值为0,而参数shmflg中设置了IPC_CREATE这个标志,则同样创建一块新的共享内存;
我们一般是通过ftok函数获取键值key
#include<sys/types.h>
#include<sys/ipc.h> key_t ftok(const char * pathname, int proj_id) /*pathname 就是指定的文件名(该文件必须是存在而且可以访问的)
id是标示符,和pathname一起完成创建键值的参数,虽然为int,但只有8个比特被使用,一般我们写一个字符代替*/
例如:
#include<sys/types.h>
#include<sys/ipc.h>
#include<stdio.h>
#include<stdlib.h> int main()
{
key_t key1,key2;
if((key1 = ftok(".",'a')) < )
{
perror("fail to ftok");
exit(EXIT_FAILURE);
}
if((key2 = ftok(".",'b')) < )
{
perror("fail to ftok");
exit(EXIT_FAILURE);
}
printf("key1 = %d\n",key1);
printf("key2 = %d\n",key2); return ;
}
(2)size:
是要建立共享内存的长度。所有的内存分配操作都是以页为单位的。所以如果一个进程只申请一块只有体格字节的内存,内存也会分配蒸蒸一页(在i386机器中一页的缺省大小PACE_SIZE = 4096B)
(3)shmflg:
指定创建或打开的标志和读写的权限(ipc_perm中的mode成员)。
有效的标志包括IPC_CREAT和IPC_EXCL,他们的功能与opene的O_CREAT和O_EXCL相当。
IPC_CREAT 如果共享内存不存在,则创建一个共享内存,否则直接打开已存在的。
IPC_EXCL 只有在共享内存不存在的时候,新的内存才建立,否则就产生错误。
/*假设键值为key,创建一个共享内存大小为4k,访问权限为0666
如果已经存在则返回其标示符*/
int shmid;
if((shmid = shmget(key, 4*1024, 0666 | IPC_CRREAT)) < 0)
{
perror("Fail to shmget");
exit(EXIT_FAILURE);
}
/*假设键值为key,创建一个共享内存大小为1k,访问权限为0666
如果已经存在则报错*/
int shmid;
if((shmid = shmget(key, , | IPC_CRREAT|IPC_EXCL)) < )
{
perror("Fail to shmget");
exit(EXIT_FAILURE);
}
step 2--------------------------->共享内存的映射
函数shmat将标示符为shmid共享内存映射到调用进程的地址空间中。
#include<sys/types.h>
#include<sys/shm.h> void * shmat(int shmid, const void *shmaddr, int shmflg);
参数说明:
shmid:要映射的共享内存区标示符
shmaddr:将共享内存映射到指定地址(若为NULL,则表示由系统自动完成映射)
shmflg:SHM_RDONLY 共享内存只读
默认0:共享内存可读写
返回值:调用成功返回映射后的地址,出错返回(void *)-1。
step3------------------------------>撤销共享内存与用户进程之间的映射
int shmdt(const void * shmadr);
参数shmaddr 是 shmat映射成功返回的地址。
注意:当一个进程不再需要共享内存段时,它将调用shmdt()系统调用取消这个段,但是这并不是从内核真正地删除这个段,而是把相关shmid_ds结构的shm_nattch域的值减1,当这个值为0时,内核才从物理上删除这个共享段。
step4-------------------------------->控制共享内存(&删除)
#inlcude<sys/ipc.h>
#include<sys/shm.h> int shmctl(int shmid, int cmd, struct shmid_ds *buf);
参数说明:
shmid 共享内存标示符ID
cmd IPC_STAT得到共享内存的状态
IPC_SET改变共享内存的状态
IPC_RMID删除共享内存
buf 是一个结构体指针。IPC_STAT的时候,取得的状态放在这个结构体中。如果要改变共享内存的状态,用这个结构体 struct shmid_ds 指定:
注意:
1.IPC_RMID命令实际上不从内核删除一个段,而是仅仅把这个段标记为删除,实际的删除发生最后一个进程离开这个共享段时。
2.当cmd为IPC_RMID时,第三个参数应为NULL。用这个函数“删除”共享内存
3.如果在代码中没有手动删除,共享内存并不会随着程序的终止而自动清理!
共享内存之——system V共享内存的更多相关文章
- Linux进程通信之System V共享内存
前面已经介绍过了POSIX共享内存区,System V共享内存区在概念上类似POSIX共享内存区,POSIX共享内存区的使用是调用shm_open创建共享内存区后调用mmap进行内存区的映射,而Sys ...
- 阐述linux IPC(五岁以下儿童):system V共享内存
[版权声明:尊重原创.转载请保留源:blog.csdn.net/shallnet 要么 .../gentleliu,文章学习交流,不用于商业用途] system V共享内存和posix ...
- UNIX环境高级编程——System V 共享内存区
共享内存区域是被多个进程共享的一部分物理内存.如果多个进程都把该内存区域映射到自己的虚拟地址空间,则这些进程就都可以直接访问该共享内存区域,从而可以通过该区域进行通信.共享内存是进程间共享数据的一种最 ...
- Linux IPC实践(9) --System V共享内存
共享内存API #include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, size_t size, int ...
- php进程(线程)通信基础--System V共享内存
PHP默认情况没有开启功能,要支持该功能在编译PHP的时候要加入下面几个选项 System V消息,--enable-sysvmsg System V信号量支持,--enable-sysvsem ...
- System V 共享内存区
1.概述 系统调用mmap通过映射一个普通文件实现共享内存.System V 则是通过映射特殊文件系统shm中的文件实现进程间的共享内存通信.也就是说,每个共享内存区域对应特殊文件系统shm中的一个文 ...
- System V共享内存介绍
(一)简单概念 共享内存作为一种进程间通信的方式,其相较于其他进程间通信方式而言最大的优点就是数据传输速率快.其内部实现的方式采用了Linux进程地址空间中的mmap文件映射区,将文件内容直接映射到各 ...
- Linux system v 共享内存
system v 共享内存 #include <sys/types.h> #include <sys/shm.h> int shmget(key_t key, size_t s ...
- System V共享内存
目录 1. 概述 2. System V共享内存API shmget shmat shmdt shmctl 3. 简单的程序 代码实现 common.h shmcreate.c shmrmid.c s ...
随机推荐
- lua 分割字符串
-- 参数:待分割的字符串,分割字符 -- 返回:子串表.(含有空串) function split(str, split_char) local sub_str_tab = {} while tru ...
- 【mysql】[Err]1267 - Illegal mix of collations(utf8_general_ci,IMPLICIT) and (utf8_unicode_ci,IMPLICIT) for operation ‘=
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
- Go IO && bufio
IO IO包 是对数据流的操作.从哪里来, 怎么处理,再到哪里去. 图片来源 https://medium.com/learning-the-go-programming-language/strea ...
- python解析库之 XPath
1. XPath (XML Path Language) XML路径语言 2. XPath 常用规则: nodename 选取此节点的所有子节点 / 从当前 ...
- cento命令之which、whereis、locate、find
[which] 查看可执行文件的位置 语法: [root@localhost ~]# which 可执行文件名称 例如: [root@localhost ~]# which passwd /usr/b ...
- java8新特性:接口的默认方法与静态方法
接口中一共可以定义三种方法: 1.抽象方法,也就是需要实现者必须实现的方法,最常见的那种 2.默认方法,不需要实现者实现 3.静态方法,不需要实现者实现 默认方法: 允许在已有的接口中添加新方法,而同 ...
- 面向对象——property
1.property特性 property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值 将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉到name是执行了一 ...
- python学习-- Django根据现有数据库,自动生成models模型文件
Django引入外部数据库还是比较方便的,步骤如下 : 创建一个项目,修改seting文件,在setting里面设置你要连接的数据库类型和连接名称,地址之类,和创建新项目的时候一致 运行下面代码可以自 ...
- 【LeetCode】Binary Tree Postorder Traversal(二叉树的后序遍历)
这道题是LeetCode里的第145道题. 题目要求: 给定一个二叉树,返回它的 后序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [3,2,1] 进阶: 递归算法很 ...
- python正则re模块
今日内容: 知识点一:正则 什么是正则: 就是用一系列具有特殊含义的字符组成一套规则,改规则用来描述具有某一特征的字符串 正则就是用来在一个大的字符串中取出符合规则的小字符串 为什么用正则: ...