共享内存区

共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据。

mmap函数

功能:将文件或者设备空间映射到共享内存区。

原型

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

参数

addr: 要映射的起始地址,通常指定为NULL,让内核自动选择

len:映射到进程地址空间的字节数

prot:映射区保护方式

flags:标志

fd:文件描述符

offset:从文件头开始的偏移量

返回值:成功返回映射到的内存区的起始地址;失败返回-1


prot

说明

PROT_READ

页面可读

PROT_WRITE

页面可写

PROC_EXEC

页面可执行

PROT_NONE

页面不可访问

flags

说明

MAP_SHARED

变动是共享的

MAP_PRIVATE

变动是私有的

MAP_FIXED

准确解释addr参数

MAP_ANONYMOUS

建立匿名映射区,不涉及文件

munmap函数

功能:取消mmap函数建立的映射

原型

int munmap(void *addr, size_t len);

参数

addr: 映射的内存起始地址

len:映射到进程地址空间的字节数

返回值:成功返回0;失败返回-1

msync函数

功能:对映射的共享内存执行同步操作

原型

int msync(void *addr, size_t len, int flags);

参数

addr: 内存起始地址

len:长度

flags:选项

返回值:成功返回0;失败返回-1


flags

说明

MS_ASYNC

执行异步写

MS_SYNC

执行同步写

MS_INVALIDATE

使高速缓存的数据失效

map注意点

映射不能改变文件的大小

可用于进程间通信的有效地址空间不完全受限于被映射文件的大小

文件一旦被映射后,所有对映射区域的访问实际上是对内存区域的访问。映射区域内容写回文件时,所写内容不能超过文件的大小。

nmap_read.c

#include <unistd.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <sys/mman.h>

#include <stdlib.h>

#include <stdio.h>

#include <errno.h>

#include <string.h>

#define ERR_EXIT(m) \

do \

{ \

perror(m); \

exit(EXIT_FAILURE); \

} while(0)

typedef struct stu

{

char name[4];

int age;

} STU;

int main(int argc, char *argv[])

{

if (argc != 2)

{

fprintf(stderr, "Usage: %s <file>\n", argv[0]);

exit(EXIT_FAILURE);

}

int fd;

fd = open(argv[1], O_RDWR);

if (fd == -1)

ERR_EXIT("open");

STU *p;

p = (STU*)mmap(NULL, sizeof(STU)*5, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

if (p == NULL)

ERR_EXIT("mmap");

int i;

for (i=0; i<10; i++)

{

printf("name = %s age = %d\n", (p+i)->name, (p+i)->age);

}

munmap(p, sizeof(STU)*10);

printf("exit ...\n");

return 0;

}

nmap_write.c

#include <unistd.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <sys/mman.h>

#include <stdlib.h>

#include <stdio.h>

#include <errno.h>

#include <string.h>

#define ERR_EXIT(m) \

do \

{ \

perror(m); \

exit(EXIT_FAILURE); \

} while(0)

typedef struct stu

{

char name[4];

int age;

} STU;

int main(int argc, char *argv[])

{

if (argc != 2)

{

fprintf(stderr, "Usage: %s <file>\n", argv[0]);

exit(EXIT_FAILURE);

}

int fd;

fd = open(argv[1], O_CREAT | O_RDWR | O_TRUNC, 0666);

if (fd == -1)

ERR_EXIT("open");

lseek(fd, sizeof(STU)*5-1, SEEK_SET);

write(fd, "", 1);

STU *p;

p = (STU*)mmap(NULL, sizeof(STU)*10, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

if (p == NULL)

ERR_EXIT("mmap");

char ch = ‘a‘;

int i;

for (i=0; i<10; i++)

{

memcpy((p+i)->name, &ch, 1);

(p+i)->age = 20+i;

ch++;

}

printf("initialize over\n");

sleep(10);

munmap(p, sizeof(STU)*10);

printf("exit ...\n");

return 0;

}

makefile:

.PHONY:clean all

CC=gcc

CFLAGS=-Wall -g

BIN=mmap_write mmap_read

all:$(BIN)

%.o:%.c

$(CC) $(CFLAGS) -c $< -o [email protected]

clean:

rm -f *.o $(BIN)

共享内存区

时间: 2024-10-06 09:38:02

共享内存区的相关文章

Linux环境编程之共享内存区(一):共享内存区简介

Spark生态圈,也就是BDAS(伯克利数据分析栈),是伯克利APMLab实验室精心打造的,力图在算法(Algorithms).机器(Machines).人(People)之间通过大规模集成,来展现大数据应用的一个平台,其核心引擎就是Spark,其计算基础是弹性分布式数据集,也就是RDD.通过Spark生态圈,AMPLab运用大数据.云计算.通信等各种资源,以及各种灵活的技术方案,对海量不透明的数据进行甄别并转化为有用的信息,以供人们更好的理解世界.Spark生态圈已经涉及到机器学习.数据挖掘.

Linux环境编程之共享内存区(二):Posix共享内存区

现在将共享内存区的概念扩展到将无亲缘关系进程间共享的内存区包括在内.Posix提供了两种在无亲缘关系进程间共享内存区的方法: 1.内存映射文件:由open函数打开,由mmap函数把得到的描述符映射到当前进程地址空间中的一个文件.(上一节就是这种技术) 2.共享内存区对象:由shm_open打开一个Posix名字(也许是在文件系统中的一个路径名),所返回的描述符由mmap函数映射到当前进程的地址空间.(本节内容) Posix共享内存区涉及以下两个步骤要求: 1.指定一个名字参数调用shm_open

system v 共享内存区

#include<sys/shm.h> int shmget(key_t key,size_t size,int oflag);    返回:成功则为共享内存区对象,出错为-1 key 的值可以是ftok的返回值,也可以是IPC_PRIVATE. ftok()               是非亲缘进程间 IPC_PRIVATE         是亲缘进程间的 size以字节为单位指定内存区的大小.当实际操作为创建一个新的共享内存区时,必须指定一个不为0的size值.如果实际操作为访问一个已存在

进程间通信(三)&mdash;&mdash;共享内存区

1.概述 共享内存区是IPC中最快的,当内存区映射到共享它的进程的地址空间,进程间数据的传递就不再涉及内核. 但是这需要某种形式的同步,最常用的是信号量. 不再涉及内核:进程不再通过执行任何进入内核的系统调用来彼此传递数据.内核必须建立允许各个进程共享该内存区的内存映射关系,然后一值管理该内存区.   管道,FIFO和消息队列的问题是,两个进程要交换信息时,这些信息必须经由内核传递. 共享内存区可以绕过这个问题,但是一般必须同步数据.   使用内存映射文件的特性,所有的I/O都不再有内核直接参与

Linux 进程通信(共享内存区)

共享内存是由内核出于在多个进程间交换信息的目的而留出的一块内存区(段). 如果段的权限设置恰当,每个要访问该段内存的进程都可以把它映像到自己的私有地址空间中. 如果一个进程更新了段中的数据,其他进程也立即会看到更新. 由一个进程创建的段,也可以由另一个进程读写. 每个进程都把它自己对共享内存的映像放入自己的地址空间. 创建共享内存区 int shmget(key_t key,size_t size,int shm-flg); 参数key既可以是IPC_PRIVATE(IPC_PRIVATE表示让

UNIX网络编程:共享内存区

IPC形式除了管道.FIFO.信号量以外,还有共享内存区和消息队列.这里主要堆共享内存进行介绍. 共享内存区是可用IPC形式中最快的.一旦这样的内存区映射到共享它的进程地址空间,这些进程间数据的传递就不再涉及内核.共享内存与其他进程通信方式相比较,不需要复制数据,直接读写内存,是一种效率非常高的进程通信方案.但它本身不提供同步访问机制,需要我们自己控制.在LINUX中,只要把共享内存段连接到进程的地址空间中,这个进程就可以访问共享内存中的地址了.为了实现往该共享内存区存放和取出数据的进程间的同步

Unix IPC之共享内存区(1)

1 共享内存区 共享内存区是可用IPC形式中最快的,只有映射和解除映射需要进入内核的系统调用,映射后对共享内存区的访问和修改不再需要系统调用(内核只要负责好页表映射和处理页面故障即可),但通常需要同步手段. 一个客户-服务器间传递文件数据的例子中,FIFO或消息队列等IPC方式通常需要4次内核-进程间的数据复制(但是Posix消息队列可使用内存映射I/O实现,就不一定4次了),每次都需要切换地址空间,开销很大:共享内存区只需要2次跨内核的数据复制. 2  mmap mmap的三个目的: 1.  

Linux环境编程之共享内存区(一):共享内存区简单介绍

共享内存区是可用IPC形式中最快的.一旦内存区映射到共享它的进程的地址空间,进程间数据的传递就不再涉及内核.然而往该共享内存区存放信息或从中取走信息的进程间通常须要某种形式的同步.不再涉及内核是指:进程不再通过运行不论什么进入内核的系统调用来彼此传递数据.内核必须建立同意各个进程共享该内存区的内存映射关系.然后一直管理内存区. 默认情况下通过fork派生的子进程并不与其父进程共享内存区. mmap函数把一个文件或一个Posix共享内存区对象映射到调用进程的地址空间.使用该函数的目的有: 1.使用

linux c编程:Posix共享内存区

Posix共享内存区:共享内存是最快的可用IPC形式.它允许多个不相关(无亲缘关系)的进程去访问同一部分逻辑内存.如果需要在两个进程之间传输数据,共享内存将是一种效率极高的解决方案.一旦这样的内存区映射到共享它的进程的地址空间,这些进程间数据的传输就不再涉及内核.这样就可以减少系统调用时间,提高程序效率.共享内存是由IPC为一个进程创建的一个特殊的地址范围,它将出现在进程的地址空间中.其他进程可以把同一段共享内存段“连接到”它们自己的地址空间里去.所有进程都可以访问共享内存中的地址.如果一个进程