共享內存映射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;
}