共享内存

来源:互联网 发布:网络整合营销 编辑:程序博客网 时间:2024/05/22 08:00

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



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

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

a)        adrr:要映射的起始地址,通常为NULL,让内核自动选择

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

c)        prot:映射区保护方式

d)       flags:标志

e)        fd:”文件描述符

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

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

Prot

说明

PROT_READ

页面可读

PROT_WAIT

页面可写

PROC_EXEX

页面可执行

PROT_NONE

页面不可访问

 

Flags

说明

MAP_SHARED

变动是共享的

MAP_PRIVATE

变动是私有的

MAP_FIXED

准确解释addr参数

MAP_ANONYMOUS

简历匿名映射区,不涉及文件



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

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

参数:

a)        addr:内存起始地址

b)       len:长度

c)        flags:选项

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

Flag

说明

MS_ASYNC

执行异步写

MS_SYNC

执行同步写

MS_INVALIDATE

使高速缓存的数据失效

 

因为内核不会立即将数据写入文件中,如果想立即返回,就可以调用该函数

map注意点:

1.        映射不能改变文件大小

2.        可用于进程间通信的有效地址不完全受限于被映射文件的大小(因为内存分配是以页为单位的,所以映射的共享内存区可能会大于文件大小)

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

int munmap(void *addr, size_t length);

功能:释放共享内存

参数:addr,共享内存起始地址,length,共享内存大小

写端:

#include<sys/mman.h>#include<unistd.h>#include<sys/types.h>#include<stdlib.h>#include<stdio.h>#include<errno.h>#include<sys/stat.h>#include<fcntl.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[1]);exit(EXIT_FAILURE);}int 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=NULL;p = (STU *)mmap(NULL, sizeof(STU) * 5, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);if (p == NULL)ERR_EXIT("mmap");char ch[4] = "abc";for (int i = 0; i < 5; i++){memcpy(p->name, ch, sizeof(ch));p->age = i;p++;}        printf("inilize end\n");        munmap(p,sizeof(STU)*5);        printf("exit...\n");        return 0;}

写端:
#include<sys/mman.h>#include<unistd.h>#include<sys/types.h>#include<stdlib.h>#include<stdio.h>#include<errno.h>#include<sys/stat.h>#include<fcntl.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[1]);exit(EXIT_FAILURE);}int fd = open(argv[1], O_RDWR);if (fd == -1)ERR_EXIT("open");STU *p=NULL;p = (STU *)mmap(NULL, sizeof(STU) * 5, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);if (p == NULL)ERR_EXIT("mmap");for (int i = 0; i < 5; i++){     printf("name = %s age=%d\n",(p+i)->name,(p+i)->age);}        munmap(p,sizeof(STU)*5);        printf("exit\n");        return 0;}