共享内存之——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 ...
随机推荐
- ajax $.post 一直报 Forbidden (CSRF token missing or incorrect.)
由于后台整合类视图代码,所以修改了写法,完了之后用下面的写法写的post请求都报 403 error $.post( "{% url 'test_record:select_node_pag ...
- 收集的免费API接口
1.IP地址调用接口 这是淘宝的IP调用API http://ip.taobao.com/service/getIpInfo.php?ip=$ip 返回值:{"code":0,&q ...
- GOPATH和GOROOT
安装指定版本golang apt-get purge golang* //删除之前安装的文件 add-apt-repository ppa:evarlast/golang-1.8 apt-get up ...
- Python使用gevent实现协程
Python中多任务的实现可以使用进程和线程,也可以使用协程. 一.协程介绍 协程,又称微线程.英文名Coroutine.协程是Python语言中所特有的,在其他语言中没有. 协程是python中另外 ...
- IDEA常用快捷键(不全)
这里使用的是默认的idea快捷键,如果修改了keymap为其他,那么不适用. 1.格式化代码:Ctrl+Alt+L(可能与QQ的冲突,建议QQ只保留方便的截图,皮) 2.在当前行最后添加分号,或自动补 ...
- nrf52裸机学习——GPIO操作
/** * @brief Function for writing a value to a GPIO pin. * * Note that the pin must be configured as ...
- 原生Ajax+springBoot实现用户登录
思路:用户输入登录信息——信息传到后台——数据库查询——比较查询结果——返回登录信息(成功/失败) html页面代码: <!DOCTYPE html> <html lang=&quo ...
- 官网下载MySQL
1)首先我们访问MySQL官网https://dev.mysql.com/,然后如下 2)我们向下拉取滚动条,来到如下界面,选择Source Code 3)向下拉取滚动条,来到如下界面,操作如下: 4 ...
- HSL颜色处理
H--色调 S--饱和度 L--亮度 HSB(HSL) 色调饱和度亮度模式 以另外一种不同的理念进行色彩的调配 H色调 0~360 圆环形式 以角度表示 S 饱和度 0~1 之间的小数 L 亮度 0~ ...
- Nginx从入门到放弃-第4章 深度学习篇
4-1 Nginx动静分离_动静分离场景演示 4-2 Nginx动静分离_动静分离场景演示1 4-3 Nginx的动静分离_动静分离场景演示2 4-4 Rewrite规则_rewrite规则的作用 4 ...