共享内存映射mmap笔记
创建映射区:mmap函数原型
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
参数
- addr:指定映射区首地址,通常穿NULL
- length:共享内存映射区大小
- prot:共享内存映射区的读写属性,PROT_READ,PROT_WRITE,PROT_READ|PROT_WRITE
- flags:标注共享内存的(进程间)共享属性,MAP_SHARED,MAP_PRIVATE
- fd:用于创建共享内存映射区的那个文件的文件描述符
- offset:偏移量,必须是4k的整数倍
返回值
- 成功:映射区首地址
- 失败:MAP_FAILED,errno
释放映射区:munmap函数原型
int munmap(void *addr, size_t length);
参数
- addr:mmap的返回值
- length:映射区大小
示例代码
#include <iostream>
#include <string>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <pthread.h>
void sys_err(const std::string& str) {
perror(str.c_str());
exit(1);
}
int main(void)
{
//文件映射指针
char* p = nullptr;
//文件描述符
int fd;
fd = open("testmap.tmp", O_RDWR | O_CREAT | O_TRUNC, 0644);
if (fd == -1) {
sys_err("open error");
}
//文件扩展大小
ftruncate(fd, 100);
int len = lseek(fd, 0, SEEK_END);
//创建映射区
p = (char*)mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);//C++中需要类型转换
if (p == MAP_FAILED) {
sys_err("mmap error");
}
//关闭文件描述符
close(fd);
//使用p对文件进行写操作
strcpy(p, "========HELLO========");
//查看p
printf("%s", p);
//释放映射区
int ret = munmap(p, len);
if(ret == -1){
sys_err("munmap error");
}
return 0;
}
注意事项
- 用于创建映射区的文件大小为0,实际指定非0大小创建映射区,总线错误
- 用于创建映射区的文件大小为0,实际指定0大小创建映射区,无效参数
- 用于创建映射区的文件属性只读,映射区属性读写,无效参数
- 创建映射区需要read权限,mmap的读写权限要<=文件的open权限,mmap只写是不行的
- 创建完映射区就可以关闭文件描述符
- offset必须是4096的整数倍(4k)
- 映射区访问权限设为MAP_PRIVATE,对内存操作不反映在磁盘上
- 映射区访问权限设为MAP_PRIVATE,只需要open文件时,有读写权限,用于创建映射区即可
mmap匿名映射区
不在磁盘上对文件有操作
例子
#include <iostream>
#include <string>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <pthread.h>
void sys_err(const std::string& str) {
perror(str.c_str());
exit(1);
}
int main(void)
{
//文件映射指针
char* p = nullptr;
//创建映射区
int len = 100;
//注意一定要有MAP_ANON参数
p = (char*)mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); //C++中需要类型转换
if (p == MAP_FAILED) {
sys_err("mmap error");
}
//写操作
strcpy(p, "99999");
//查看p
printf("%s", p);
//释放映射区
int ret = munmap(p, len);
if (ret == -1) {
sys_err("munmap error");
}
return 0;
}