mmap实现共享内存

简介: mmap实现共享内存

可以简单地理解

共享内存:进程A中的一块内存空间和进程B中操作的一块内存空间是同一块内存空间

更详细的原理可以参考,下面主要是如何使用mmap去实现共享内存

一、mmap参数

通过man手册可以知道

addr:共享内存的地址,如果为NULL,则会自动分配一块内存

length:共享内存的长度

prot:内存保护的一些flags(比如说:匿名,读,写权限等)

flags:是否对其他进程可见,更新是否会传递到底层文件

fd:文件描述符(用于对内存初始化)

offset:偏移量(用于初始化,offset从fd哪个位置开始读取,length可以表示读取长度)

二、内存不共享情况

利用malloc去创建一块内存

利用fork()去创建一个子进程,子进程将字符写入到共享内存中,主进程将从内存中读数据。(能读到数据就说明,不同进程之间共享了数据)

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <fcntl.h>
//创建共享内存
void *shm_mmap_alloc(int size) {
  void *addr = mmap(NULL, size, PROT_READ|PROT_WRITE, 
    MAP_ANON | MAP_SHARED, -1, 0);
  if (addr == MAP_FAILED) {
    return NULL;
  }
  return addr;
}
//释放共享内存
int shm_mmap_free(void *addr, int size) {
  return munmap(addr, size);
}
int main() {
    char* addr=(char*)malloc(1024*1024);
  pid_t pid = fork();//创建子进程
  if (pid == 0) {//子进程中写字符
    int i = 0;
    while (i < 26) {
      addr[i] = 'a' + i;
      addr[++i] = '\0';
      sleep(1);
    }   
  } else if (pid > 0) {//父进程中读字符
    int i = 0;
    while (i ++ < 26) {     
      printf("client : %s\n", addr);
      sleep(1);       
    }   
  }
}

可以发现主进程读不到任何数据

三、内存共享

在其他不变的情况下,通过mmap来创建一块共享内存,munmap去释放一块共享内存。

mmap创建内存代替malloc

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <fcntl.h>
//创建共享内存
void *shm_mmap_alloc(int size) {
  void *addr = mmap(NULL, size, PROT_READ|PROT_WRITE, 
    MAP_ANON | MAP_SHARED, -1, 0);
  if (addr == MAP_FAILED) {
    return NULL;
  }
  return addr;
}
//释放共享内存
int shm_mmap_free(void *addr, int size) {
  return munmap(addr, size);
}
int main() {
  char *addr= (char *)shm_mmap_alloc(1024 * 1024);
  pid_t pid = fork();//创建子进程
  if (pid == 0) {//子进程中写字符
    int i = 0;
    while (i < 26) {
      addr[i] = 'a' + i;
      addr[++i] = '\0';
      sleep(1);
    }   
  } else if (pid > 0) {//父进程中读字符
    int i = 0;
    while (i ++ < 26) {     
      printf("client : %s\n", addr);
      sleep(1);       
    }   
  }
  shm_mmap_free(addr, 1024);
}

运行后,可以发现主进程能读出子进程里的数据,因此是内存共享的。

换种写法

利用从"/dev/zero"中读数据,读到的数据都是空的,都是0,因此可以利用 该文件描述符(fd)用来初始化一块内存。

/dev/zero是什么意思

void *shm_mmap_alloc(int size) {
  int fd = open("/dev/zero", O_RDWR);
  void *addr = mmap(NULL, size, PROT_READ|PROT_WRITE, 
     MAP_SHARED, fd, 0);
  close(fd);
  if (addr == MAP_FAILED) {
    return NULL;
  }
  return addr;
}


相关文章
|
6月前
|
消息中间件 存储 缓存
Linux内存映射mmap
Linux内存映射mmap
80 0
|
存储 Linux
Linux 共享内存mmap,进程通信
Linux 共享内存mmap,进程通信
111 0
【共享内存】
【共享内存】
70 0
|
存储 缓存 Java
mmap内存映射原理
mmap内存映射原理
226 0
|
网络协议
共享内存
共享内存
213 0
|
Linux
Linux系统编程-进程间通信(mmap内存映射)
前面文章介绍了进程间常用的通信方式: 无名管道和命名管道,这篇文章介绍内存映射,内存映射在多进程访问文件读写的时候非常方便。
252 0
|
Linux Android开发 Windows
【Binder 机制】进程通信 | 用户空间与内核空间 | MMU 与虚拟内存地址
【Binder 机制】进程通信 | 用户空间与内核空间 | MMU 与虚拟内存地址
279 0
【Binder 机制】进程通信 | 用户空间与内核空间 | MMU 与虚拟内存地址
|
Linux
基于NETLINK的内核与用户空间共享内存的实现
一、前言 前些日子,开发中用到了netlink来实现内核与用户空间共享内存,写点笔记与大家分享。因为我对这块也不了解,写出来的东西一定存在很多错误,请大家批评指正~ 内核与用户空间共享内存的关键是,用户空间必须得知共享内存的起始地址,这就要求内核空间应该有一种通信机制来通知用户空间。已经有Godbach版主等人用proc文件系统实现了(可以google '共享内存 内核 用户空间'),很显然任何内核空间与用户空间的通信方法都可资利用。本文主要讲基于NETLINK机制的实现。 二、NETLINK简介 netlink在linux的内核与用户空间通信中用得很多(但具体例子我举不出,因为我不清楚~~
328 0
|
Linux 消息中间件 索引
Linux内存管理之mmap详解
作者:freeboy1015 来源:http://lib.csdn.net/article/linux/62126 一. mmap系统调用 mmap系统调用 mmap将一个文件或者其它对象映射进内存。
966 0