内存映射区简介
存储映射I/O (Memory-mapped I/O) 使一个磁盘文件与存储空间中的一个缓冲区相映射。从缓冲区中取数据,就相当于读文件中的相应字节;将数据写入缓冲区,则会将数据写入文件。这样,就可在不使用read和write函数的情况下,使用地址(指针)完成I/O操作。
使用存储映射这种方法,首先应通知内核,将一个指定文件映射到存储区域中。这个映射工作可以通过mmap函数来实现。

mmap函数
- 函数作用:建立存储映射区
- 函数原型:void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
- 函数返回值: 成功:返回创建的映射区首地址; 失败:MAP_FAILED宏
- 参数:
- addr: 指定映射的起始地址, 通常设为NULL, 由系统指定
- length:映射到内存的文件长度
- prot: 映射区的保护方式, 最常用的:读:PROT_READ写:PROT_WRITE读写:PROT_READ | PROT_WRITE
- flags: 映射区的特性, 可以是
- MAP_SHARED: 写入映射区的数据会写回文件, 且允许其他映射该文件的进程共享。
- MAP_PRIVATE: 对映射区的写入操作会产生一个映射区的复制(copy-on-write), 对此区域所做的修改不会写回原文件。
- fd:由open返回的文件描述符, 代表要映射的文件。
- offset:以文件开始处的偏移量, 必须是4k的整数倍, 通常为0, 表示从文件头开始映射。
例1:以用mmap进行父子进程通信:
代码如下:
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
using namespace std;
int main()
{
//使用mmap函数建立共享映射区
int fd = open("./test.log", O_RDWR);//打开文件,获取mmap的参数文件描述符
if(fd<0)
{
perror("open error");
return -1;
}
int len = lseek(fd, 0, SEEK_END);//打开的文件用lseek获取文件大小
//函数原型:void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
void * addr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
//void * addr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
if(addr==MAP_FAILED)//函数调用失败,返回Linux所规定的宏
{
perror("mmap error");
return -1;
}
close(fd);//创建映射区的过程中,隐含着一次对映射文件的读操作,将文件内容读取到映射区
//映射区的释放与文件关闭无关,只要映射建立成功,文件可以立即关闭。
//创建子进程
pid_t pid = fork();
if(pid<0)
{
perror("fork error");
return -1;
}
else if(pid>0)
{
//void *memcpy(void *dest, const void *src, size_t n); 内存拷贝函数将后者的内容拷贝到前者
memcpy(addr, "hello 你好!!", strlen("hello 你好!!"));
wait(NULL);//回收子进程
}
else if(pid==0)
{
sleep(1);
char *p = (char *)addr;//强制类型转换
printf("[%s]", p);
}
return 0;
}
~
~
运行结果如下:

子进程打印出来父进程写入的字符串。
例2:进行没有血缘关系进程通信
进程A(执行写的功能):
//使用mmap函数完成两个不相干进程间通信
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
using namespace std;
int main()
{
//使用mmap函数建立共享映射区
//void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
int fd = open("./mmap.log", O_RDWR);
if(fd<0)
{
perror("open error");
return -1;
}
int len = lseek(fd, 0, SEEK_END);
//建立共享映射区
void * addr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if(addr==MAP_FAILED)
{
perror("mmap error");
return -1;
}
memcpy(addr, "0123456789", strlen("0123456789"));
return 0;
}
进程B(执行读的功能):
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
using namespace std;
int main()
{
//使用mmap函数建立共享映射区
//void *mmap(void *addr, size_t length, int prot, int flags,
// int fd, off_t offset);
int fd = open("./mmap.log", O_RDWR);
if(fd<0)
{
perror("open error");
return -1;
}
int len = lseek(fd, 0, SEEK_END);
//建立共享映射区
void * addr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if(addr==MAP_FAILED)
{
perror("mmap error");
return -1;
}
char buf[64];
memset(buf, 0x00, sizeof(buf));
memcpy(buf, addr, strlen((char*)addr));
cout << "buf==[" << buf << "]" << endl;
return 0;
}
先执行A,随后执行B,保证读到写入的内容:

看到[01123456789]已经写入 mmap.log中,实现了不相干进程之间的通信.
最后
以上就是能干龙猫最近收集整理的关于用mmap函数建立存储映射区进行进程间通信的全部内容,更多相关用mmap函数建立存储映射区进行进程间通信内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复