共享存储映射
存储映射I/O使一个词磁盘文件与存储空间中的一个缓冲区相映射
于是当从缓冲区中取数据,就相当于读文件中的相应字节。与此类推,将数据存入缓冲区,则相应的字节数就自动写入文件。这样,就可在不适合read和write函数的情况下,使用地址(指针)完成I/O操作。
共享内存可以说是最有用的进程间通信方式,也是最快的PC形式,因为进程可以直接读写内存,而不需要任何数据的拷贝。
存储映射函数
功能:一个文件或者其他对象映射进内存
mmap函数 void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
addr:指定映射的起始地址,通常设为NULL,由系统指定
length:映射到内存的文件长度
prot:映射区的保护方式
flags:映射区的特性
fd:由open返回的文件描述符,代表要映射的文件
offset:以文件开始处的偏移量,必须是4k的整数倍,通常为0,表示从文件头开始映射
munmap函数
功能:释放内存映射区
参数:addr:使用mmap函数创建的映射区的首地址
length:映射区文件的大小
返回值: 成功:0
失败:-1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
int main(void){
int fd = -1;
int ret = -1;
void *addr = NULL;
fd = open("txt",O_RDWR);
if(-1 == fd){
perror("open");
return 1;
}
addr = mmap(NULL,1024,PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(addr == MAP_FAILED){
perror("mmap");
return 1;
}
printf("ok.......");
close(fd);
memcpy(addr, "1234567890",10);
munmap(addr,1024);
return 0;
}
父子进程使用存储映射通信
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/wait.h>
int main(void){
int fd = -1;
int ret = -1;
pid_t pid = -1;
void *addr = NULL;
fd = open("txt",O_RDWR);
if(-1 == fd){
perror("open");
return 1;
}
addr = mmap(NULL,1024,PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(addr == MAP_FAILED){
perror("mmap");
return 1;
}
printf("ok.......");
close(fd);
pid = fork();
if(-1 == pid){
perror("fork");
return 1;
}
//child process
if(0 == pid){
memcpy(addr,"ABCDEGHJIL",10);
}else{
wait(NULL);
//parent process
printf("addr:%s\n",(char*)addr);
}
munmap(addr,1024);
return 0;
}
ok.......ok.......addr:ABCDEGHJILaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaad
匿名映射实现父子间通信
通过使用我们发现,食欲哦那个映射区来完成文件读写操作十分方便,父子进程间通信也比较容易。但缺陷是,每次创建映射区一定要依赖一个文件才能实现。
通常为了建立映射区要open一个temp文件,创建好了再unlink、close掉,比较麻烦。可以直接使用匿名映射来替代。
其实linux系统给我们提供了创建匿名映射区的方法,无需依赖一个文件即可创建映射区。同样需要借助标志位参数flags来指定。
使用MAP_ANONYMOUS(或MAP_ANON)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void){
int ret = -1;
pid_t pid = -1;
void *addr = NULL;
//创建匿名映射
addr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if(MAP_FAILED == addr){
perror("mmap");
return 1;
}
//创建进程
pid = fork();
if(-1 == pid){
perror("fork");
munmap(addr,4096);
return 1;
}
//父子进程通信
if(0 == pid){
//子进程写
memcpy(addr, "1234567890",10);
}
else{
//父进程读
wait(NULL);
printf("parent process %s\n",(char*)addr);
}
munmap(addr,4096);
return 0;
}
输出结果:
parent process 1234567890