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共享内存的更多相关文章

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

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

  2. 阐述linux IPC(五岁以下儿童):system V共享内存

    [版权声明:尊重原创.转载请保留源:blog.csdn.net/shallnet 要么 .../gentleliu,文章学习交流,不用于商业用途]         system V共享内存和posix ...

  3. UNIX环境高级编程——System V 共享内存区

    共享内存区域是被多个进程共享的一部分物理内存.如果多个进程都把该内存区域映射到自己的虚拟地址空间,则这些进程就都可以直接访问该共享内存区域,从而可以通过该区域进行通信.共享内存是进程间共享数据的一种最 ...

  4. Linux IPC实践(9) --System V共享内存

    共享内存API #include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, size_t size, int ...

  5. php进程(线程)通信基础--System V共享内存

    PHP默认情况没有开启功能,要支持该功能在编译PHP的时候要加入下面几个选项  System V消息,--enable-sysvmsg   System V信号量支持,--enable-sysvsem ...

  6. System V 共享内存区

    1.概述 系统调用mmap通过映射一个普通文件实现共享内存.System V 则是通过映射特殊文件系统shm中的文件实现进程间的共享内存通信.也就是说,每个共享内存区域对应特殊文件系统shm中的一个文 ...

  7. System V共享内存介绍

    (一)简单概念 共享内存作为一种进程间通信的方式,其相较于其他进程间通信方式而言最大的优点就是数据传输速率快.其内部实现的方式采用了Linux进程地址空间中的mmap文件映射区,将文件内容直接映射到各 ...

  8. Linux system v 共享内存

    system v 共享内存 #include <sys/types.h> #include <sys/shm.h> int shmget(key_t key, size_t s ...

  9. System V共享内存

    目录 1. 概述 2. System V共享内存API shmget shmat shmdt shmctl 3. 简单的程序 代码实现 common.h shmcreate.c shmrmid.c s ...

随机推荐

  1. C# 用qq邮箱发邮件

    一.在企业的QQ邮箱中开启POP3/SMTP服务 开启服务时,授权密码保存好. 二.示例 public static string UserName = ""; // 企业邮箱 p ...

  2. d3.js--02(data和datum原理)

    原文链接: http://d3.decembercafe.org/pages/lessons/3.html 解析一下data和datum原理: datum():绑定一个数据到选择集上 data():绑 ...

  3. 【差分约束】poj1275Cashier Employment

    比较经典的差分约束 Description A supermarket in Tehran is open 24 hours a day every day and needs a number of ...

  4. Python爬虫系列-Requests库详解

    Requests基于urllib,比urllib更加方便,可以节约我们大量的工作,完全满足HTTP测试需求. 实例引入 import requests response = requests.get( ...

  5. 【Kafka】搭建和测试等问题

    1.安装启动kafka #跳转到下载目录cd /opt/setup # 下载安装包 wget http://mirror.bit.edu.cn/apache/kafka/0.10.2.0/kafka_ ...

  6. DeepFaceLab: SSE,AVX, OpenCL 等版本说明!

    Deep Fake Lab早期只有两个版本,一个是专门正对NVIDIA显卡的CUDA9的版本,另一个是支持CPU的版本. 三月初该项目作者对tenserFlow,Cuda的版本进行了升级,预编译的软件 ...

  7. leetcode-6-basic

    解题思路: 这道题真实地反映了我今晚有多脑残=.=只需要从根号N开始向前找,第一个能被N整除的数就是width,然后存到结果就 可以了.因为离根号N越近,width越大,与length的差越小. ve ...

  8. AreYouBusy HDU - 3535 (dp)

    AreYouBusy Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  9. 水题:HDU1716-排列2

    排列2 Problem Description Ray又对数字的列产生了兴趣: 现有四张卡片,用这四张卡片能排列出很多不同的4位数,要求按从小到大的顺序输出这些4位数. Input 每组数据占一行,代 ...

  10. 《鸟哥的Linux私房菜》学习笔记(3)——根文件系统

    一.Linux目录结构 rootfs:根文件系统,根是"/". 1./boot 系统启动相关的文件,如内核.intrd.以及grub(bootloader) root@hao:~# ...