共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式,因为进程可以直接读写内存,而不需要任何数据的拷贝。对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次数据: 一次从输入文件到共享内存区,另一次从共享内存区到输出文件。实际上,进程之间在共享内存时,并不总是读写少量数据后就解除映射,有新的通信时,再重新建立共享内存区域。而是保持共享区域,直到通信完毕为止,这样,数据内容一直保存在共享内存中,并没有写回文件。共享内存中的内容往往是在解除映射时才写回文件的。因此,采用共享内存的通信方式效率是非常高的。两个不同进程A、B共享内存的意思是,同一块物理内存被映射到进程A、B各自的进程地址空间,类似虚拟内存。进程A可以即时看到进程B对共享内存中数据的更新,反之亦然。由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以。

内存映射技术:

内存映射文件,是由一个文件到一块内存的映射。Win32提供了允许应用程序把文件映射到一个进程的函数(CreateFileMapping)。内存映射文件与虚拟内存有些类似,通过内存映射文件可以保留一个地址空间的区域,同时将物理存储器提交给此区域,内存文件映射的物理存储器来自一个已经存在于磁盘上的文件,而且在对该文件进行操作之前必须首先对文件进行映射。使用内存映射文件处理存储于磁盘上的文件时,将不必再对文件执行I/O操作(直接操作文件映射到的内存)(处理存储于磁盘上的文件时,若该文件已经调入内存,则直接访问该内存,该内存是属于进程地址空间的,否则类似缺页中断,从外存中调入该文件,该文件调入到的内存地址是固定的,而处理普通文件,每次需要读写该文件时,都需要进行IO操作,调入到内存中不同地址),使得内存映射文件在处理大数据量的文件时能起到相当重要的作用。

File mapping allows the process to use both random input and output (I/O) and sequential I/O. It also allows the process to work

efficiently with a large data file, such as a database, without having to map the whole file into memory. Multiple processes can

also use memory-mapped files to share data.

有两种类型的内存映射文件:
1.共享型,在线性区页上的任何写操作都会修改磁盘上的文件;而且如果进程对共享映射中的一个页进行写,那么这种修改对于其他映射了这同一文件的所有进程来说都是可见的。所以内存映射文件也可以作为进程通信的一种方式。
2.私有型,当进程创建的映射只是为读文件,而不是写文件时才会使用这种映射。出于这种目的,私有映射的效率要比共享映射的效率更高。但是对私有映射页的任何写操作都会使内核停止映射该文件中的页。因此写操作既不会改变磁盘上的文件,对访问相同文件的其他进程也是不可见的。但是私有内存映射中的页会因为其他进程对文件的修改而更新。

采用读写函数的文件操作,至少要经过:把要处理的文件内容加载到系统内存,再从系统内存到用户指定的内存,如果你多次读写文件,就会是多次的这个 加载、复制 的操作。
而内存映射就是加载一次而已,之后就都在内存中并且可以直接使用了。

mmap()及其相关系统调用

mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存(即将文件加载到内存中的某个区域)。普通文件被映射到进程地址空间后,进程可以向访问普通内存一样对文件进行访问(类似虚拟内存),不必再调用read(),write()等操作。

mmap()系统调用形式如下:

void* mmap ( void * addr , size_t len , int prot , int flags , int fd , off_t offset )

mmap的作用是映射文件描述符fd指定文件的 [off,off + len]区域至调用进程的[addr, addr + len]的内存区域,

返回值:若成功则返回映射区的起始地址,若出错则返回MAP_FAILED

参数fd为即将映射到进程空间的文件描述字,一般由open()返回,同时,fd可以指定为-1,此时须指定flags参数中的

MAP_ANON,表明进行的是匿名映射(不涉及具体的文件名,避免了文件的创建及打开,很显然只能用于具有亲缘关系的

进程间通信)。

len是映射到调用进程地址空间的字节数,它从被映射文件开头offset个字节开始算起。

prot 参数指定共享内存的访问权限。可取如下几个值的或:PROT_READ(可读) , PROT_WRITE (可写), PROT_EXEC (可执行), PROT_NONE(不可访问)。

flags由以下几个常值指定:MAP_SHARED , MAP_PRIVATE , MAP_FIXED,其中,MAP_SHARED , MAP_PRIVATE必

选其一,而MAP_FIXED则不推荐使用。

offset参数一般设为0,表示从文件头开始映射。

参数addr指定文件应被映射到进程空间的起始地址,一般被指定一个空指针,此时选择起始地址的任务留给内核来完成。函

数的返回值为最后文件映射到进程空间的地址,进程可直接操作起始地址为该值的有效地址。

通过共享映射的方式修改文件:

#include<stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <error.h> #define BUF_SIZE 100 int main(int argc, char **argv)
{
int fd, nread, i;
struct stat sb;
char *mapped, buf[BUF_SIZE];
for (i = ; i < BUF_SIZE; i++) {
buf[i] = '#';
} if ((fd = open(argv[], O_RDWR)) < ) {
perror("open");
} if ((fstat(fd, &sb)) == -) {
perror("fstat");
} if ((mapped = (char *)mmap(NULL, sb.st_size, PROT_READ |PROT_WRITE, MAP_SHARED, fd, )) == (void *)-)
{
perror("mmap");
} close(fd);
printf("%s", mapped);
mapped[] = '';
if ((msync((void *)mapped, sb.st_size, MS_SYNC)) == -)
{
perror("msync");
}
if ((munmap((void *)mapped, sb.st_size)) == -)
{
perror("munmap");
}
return ;
}

参考:

http://blog.csdn.net/chdhust/article/details/8159397

http://www.cnblogs.com/Anker/archive/2013/01/16/2862800.html

【APUE】进程间通信之共享存储(mmap函数)的更多相关文章

  1. 共享内存:mmap函数实现

    内存映射的应用: 以页面为单位,将一个普通文件映射到内存中,通常在须要对文件进行频繁读写时使用,这样用内存读写代替I/O读写,以获得较高的性能; 将特殊文件进行匿名内存映射,能够为关联进程提供共享内存 ...

  2. linux 进程间通信——内存共享映射mmap和munmap

    IPC三种通信机制是指:信号量.共享内存.消息队列,   信号量:通过操作系统中的PV操作来实现: 共享内存:申请一块内存,进程A往共享内存中写,其他的进程就可以通过读出共享内存中的内容来获取进程A所 ...

  3. UNIX环境高级编程——存储映射I/O(mmap函数)

         共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式,因为进程可以直接读写内存,而不需要任何数据的拷贝.对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共 ...

  4. 【Linux 应用编程】进程管理 - 进程间通信IPC之共享内存 mmap

    IPC(InterProcess Communication,进程间通信)是进程中的重要概念.Linux 进程之间常用的通信方式有: 文件:简单,低效,需要代码控制同步 管道:使用简单,默认阻塞 匿名 ...

  5. 【windows 操作系统】进程间通信(IPC)简述|无名管道和命名管道 消息队列、信号量、共享存储、Socket、Streams等

    一.进程间通信简述 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进 ...

  6. 共享内存简介和mmap 函数

    一.共享内存简介 共享内存区是最快的IPC形式,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据. 即每个进程地址空间都有一个共享存储器的映射区,当这块区 ...

  7. Linux 进程间通信(一)(经典IPC:消息队列、信号量、共享存储)

    有3种称作XSI IPC的IPC:消息队列.信号量.共享存储.这种类型的IPC有如下共同的特性. 每个内核中的IPC都用一个非负整数标志.标识符是IPC对象的内部名称,为了使多个合作进程能够在同一IP ...

  8. linux进程间通信之共享内存篇

    本文是对http://www.cnblogs.com/andtt/articles/2136279.html中共享内存(上)的进一步阐释说说明 1 共享内存的实现原理 共享内存是linux进程间通讯的 ...

  9. Linux环境进程间通信(五): 共享内存(下)

    linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...

随机推荐

  1. Linux之用户权限管理

    chmod(更改目录或文件权限) 在linux中,文件的权限分为3中,拥有者,群组,其他人.而chmod则是对权限更改的命令. u 表示该文件的拥有者,g 表示与该文件的拥有者属于同一个组,o 表示其 ...

  2. String系列之replaceAll方法替换.

    直接使用String类的replaceall方法的第一个参数并不是简单的字符串,而是一个正则表达式.在正则表达式中,英文点号(.)表示任意字符,所以你原先的写法会把所有字符都替换成空白. 转义使用所以 ...

  3. 尺取法 || POJ 2739 Sum of Consecutive Prime Numbers

    给一个数 写成连续质数的和的形式,能写出多少种 *解法:先筛质数 然后尺取法 **尺取法:固定区间左.右端点为0,如果区间和比目标值大则右移左端点,比目标值小则右移右端点               ...

  4. 【2019.5.19】接口测试及python基础(一)

      一.接口 1.什么是接口: 简单的说,接口就是从数据库获取数据. 2.前端和后端: 2.1前端client: 对于web来说,打开的网页,我们所看到的就是前端,前端语言包括html.JS.CSS: ...

  5. Maven实战读书笔记(六):Maven灵活构建

    Maven为了支持构建的灵活性,内置了3大特性,即:属性.Profile和资源过滤. 6.1 Maven属性 Maven的属性与Java代码的常量有异曲同工之妙,都是为了消除重复,对相关内容进行统一管 ...

  6. xcode中自定义log打印

    打印内容包括 在哪个文件中 ? 在哪个方法中? 将要执行什么操作?   // 此打印实现前提: // 1.在.pch文件中实现自定义log打印方法,log名换为LCLog // 2.定义一个宏obje ...

  7. 前端打包--source-map=false作用

    参考:http://www.cnblogs.com/axl234/p/6500534.htmlng serve默认会产生.map文件,该文件保存有原始代码与运行代码的映射关系, 浏览器可以通过它找到原 ...

  8. jquery 拖动(Draggable) 约束运动,输出数组排序Array

    <!doctype html><html lang="en"><head> <meta charset="utf-8" ...

  9. jdk环境变量配置至第一个简单程序运行成功

    桌面右键单击我的电脑,属性,高级,环境变量,然后再系统变量中配置(也可在用户变量中配置) 在配置环境变量时限查看是否已存在变量名称,有则添加路径,没有则创建再添加路径 /* JAVA_HOME% C: ...

  10. tomcat创建用户

    进入manager App时需要用户名+密码 输入错误时会出现页面如下: ​ 根据提示去服务器中找到tomcat目录下的tomcat-user.xml文件 在指定位置添加语句 <user use ...