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

IPC三种通信机制是指:信号量、共享内存、消息队列,

信号量:通过操作系统中的PV操作来实现;

共享内存:申请一块内存,进程A往共享内存中写,其他的进程就可以通过读出共享内存中的内容来获取进程A所传送的信息;

消息队列:创建一个消息队列,进程A往队列里面写,那么进程B通过读队列中的容来获取进程A传送的信息。

  mmap可以把磁盘文件的一部分直接映射到内存,这样文件中的位置直接就有对应的内存地址,对文件的读写可以直接用指针来操做而不需要read/write函数。

#include <sys/mman.h>

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
int munmap(void *addr, size_t length);

  

  如果addr参数为NULL,内核会自己在进程地址空间中选择合适的地址建立映射。如果addr不是NULL,则给内核一个提示,应该从什么地址开始映射,内核会选择addr之上的某个合适的地址开始映射。建立映射后,真正的映射首地址通过返回值可以得到。len参数是需要映射的那一部分文件的长度。off参数是从文件的什么位置开始映射,必须是页大小的整数倍(在32位体系统结构上通常是4K)。filedes是代表该文件的描述符。 
   
prot参数有四种取值: 
  1)PROT_EXEC 表示映射的这一段可执行,例如映射共享库 
  2)PROT_READ 表示映射的这一段可读 
  3)PROT_WRITE 表示映射的这一段可写 
  4) PROT_NONE 表示映射的这一段不可访问 
    
flag参数有很多种取值,这里只讲两种常用的,其它取值可查看mmap(2)

  • MAP_SHARED 多个进程对同一个文件的映射是共享的,一个进程对映射的内存做了修改,另一个进程也会看到这种变化。
  • MAP_PRIVATE 多个进程对同一个文件的映射不是共享的,一个进程对映射的内存做了修改,另一个进程并不会看到这种变化,也不会真的写到文件中去。

* 如果mmap成功则返回映射首地址,如果出错则返回常数MAP_FAILED。当进程终止时,该进程的映射内存会自动解除,也可以调用munmap解除映射。munmap成功返回0,出错返回-1。

/* 运行前准备 */
[email protected]:~$ vi hello
[email protected]:~$ cat hello
helloworld
[email protected]:~$ od -tx1 -tc hello
0000000 68 65 6c 6c 6f 77 6f 72 6c 64 0a
        h  e  l  l  o  w  o  r  l  d  \n
0000013
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/mman.h>

int main(void)
{
    int fd, *p, len;
    fd = open("hello",O_RDWR);
    if(fd < 0)
    {
        perror("open");
        exit(1);
    }
    //获取文件长度
    len = lseek(fd, 0, SEEK_END);
    //建立映射
    p = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    if(p == MAP_FAILED)
    {//如果失败,记住这种检测方式
        perror("mmap");
        exit(1);
    }
    //即使关闭文件也不会释放映射
    close(fd);
    //由于是共享映射,所以映射源也会被修改
    p[0] = 0x30313233;

    munmap(p, len);

    return 0;
}

/* 运行后结果(小端存储的原因) */
[email protected]:~$ cat hello
3210oworld
[email protected]:~$ od -tx1 -tc hello
0000000 33 32 31 30 6f 77 6f 72 6c 64 0a
        3  2  1  0  o  w  o  r  l  d  \n
0000013
利用内存映射的特性,也可以用于进程间的通信,但是要注意的是:
1、用于进程间通信时,一般设计成结构体,来传输通信的数据
2、进程间通信的文件,应该设计成临时文件(即创建文件,使用文件,删除文件)
3、 当报总线错误时,优先查看共享文件是否有存储空间 
时间: 2024-08-07 20:25:19

linux 进程间通信——内存共享映射mmap和munmap的相关文章

Linux进程间通信—使用共享内存

Linux进程间通信-使用共享内存 转自: https://blog.csdn.net/ljianhui/article/details/10253345 下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物理内存.进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像

Linux进程间通信--shmget()共享内存(二)

共享内存区域是被多个进程共享的一部分物理内存.如果多个进程都把该内存区域映射到自己的虚拟地址空间,则这些进程就都可以直接访问该共享内存区域,从而可以通过该区域进行通信.共享内存是进程间共享数据的一种最快的方法,一个进程向共享内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容.这块共享虚拟内存的页面,出现在每一个共享该页面的进程的页表中.但是它不需要在所有进程的虚拟内存中都有相同的虚拟地址. 图 共享内存映射图 象所有的 System V IPC对象一样,对于共享内存对象的获取

Linux进程间通信——使用共享内存

下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物理内存.进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存一样.而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程. 特别提醒:共

Linux进程间通信之共享内存

一,共享内存  内核管理一片物理内存,允许不同的进程同时映射,多个进程可以映射同一块内存,被多个进程同时映射的物理内存,即共享内存.  映射物理内存叫挂接,用完以后解除映射叫脱接. 1,共享内存的特点: 优点:是最快的IPC. 缺点:要编程者自己实现对共享内存互斥访问.如何实现? 2,编程模型:具体函数的用法可以用man手册查看(强力推荐) 进程A: writeshm.c     1) 获得key, ftok()     2) 使用key来创建一个共享内存 shmget()      3) 映射

Linux进程间通信——使用共享内存(转)

这篇文章将讲述别一种进程间通信的机制--信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信--使用信号.下面就进入信号量的讲解. 一.什么是信号量 为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域.临界区域是指执行数据更新的代码需要独占式地执行.而信号量就可以提供这样的一种访问机制,让一个临界区同

C/C++ 进程间通信 内存共享

介绍内存共享前,说下之前的误区,觉得,可以用指针来在父子进程中传递数据,其实,在fork()后,父子进程的地址空间是相互独立的!所以在父子进程间传递指针是没有意义的. 这里就涉及到物理地址和逻辑地址(或称虚拟地址)的概念. 从逻辑地址到物理地址的映射称为地址重定向.分为: 静态重定向--在程序装入主存时已经完成了逻辑地址到物理地址和变换,在程序执行期间不会再发生改变. 动态重定向--程序执行期间完成,其实现依赖于硬件地址变换机构,如基址寄存器. 逻辑地址:CPU所生成的地址.CPU产生的逻辑地址

Linux进程间通信--内存映射

一  内存映射概述 从原理上讲,Linux系统利用已有的存储管理机制可以很自然的实现进程间的共享存储.对于一段物理存储空间,只需通过进程的虚存管理机构就可以映射到各自的3G用户地址空间中.通过这种映射,在不同进程看来"私有"的数据事实上是同一段内存单元,它们被这些不同的进程所共享. 在Linux系统实际运行时,内存中的页面要经常被换入或换出,共享存储区中的页面也不例外.一般而言,内存页面的换入/换出过程采用两种方式进行: 1. 普通页面因长时间未得到访问而被内核线程kswaps在系统空

Linux进程间通信--shmget()共享内存(一)

大多数共享内存的具体实现,都是把由不同进程之间共享的内存映射为同一段物理内存. 多个进程都把该物理内存区域映射到自己的虚拟地址空间,这些进程就都可以直接访问该共享内存区域,从而可以通过该区域进行通信. 共享内存允许两个不相关的进程访问同一段物理内存, 由于数据不需要在不同的进程间复制,所以它是在两个正在运行的进程之间传递数据的一种非常有效的方式,一个进程向共享内存区域写入数据,共享该区域的所有进程就可以立刻看到其中的数据内容. 注意: 1.如上图所示,共享虚拟内存的页面,出现在每一个共享该页面的

linux进程间通信之共享内存学习记录

进程 狭义定义:进程是正在运行的程序的实例(an instance of a computer program that is being executed). 广义定义:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动.它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元. 进程的概念主要有两点:第一,进程是一个实体.每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region).数据区域(data region)和堆