WIndows与Linux中的文件内存映射
Windows 内存映射
这里所说的内存映射,并不是MDL的内存映射,只是文件映射内核对象再映射到当前应用程序的地址空间。
我们知道,目前操作系统都是使用虚拟地址空间,那么X86下,4KB对齐的情况下,页目录指针4字节,4KB/4=1024,页表同样是4字节指针,4KB/4=1024,那么对应最大物理地址可以为1024*1024*4 = 4GB。
内存映射其实就是将多个进程页表映射的真实物理地址映射为相同的物理地址。
使用
- 至少需要一个文件内核对象CreateFile或任何能获得文件句柄的方式
- 创建文件映射内核对象 CreateFileMapping
- 映射到当前应用程序的地址空间 MapViewOfFile
总的说来确实比Linux中麻烦一些,多了一个API调用。其实很简单,来看看代码
#include "pch.h"
#include <iostream>
#include <windows.h>
#define BUF_SIZE 1024
TCHAR mappingName[] = TEXT("NameOfMappingObject"); // 共享内存的名字
int main()
{
// 也可以不使用createfile ,使用createfile的好处是,进程通信结束,文件还存在着。
HANDLE hFile = CreateFile(TEXT("d:\\test.dat"), GENERIC_READ | GENERIC_WRITE,0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
// 如果想强制系统将缓存数据写入到设备,可以调用FlushFileBuffers;
if (hFile == NULL)
{
printf("create file error!");
return 0;
}//这里我没有用INVALID_HANDLE_VALUE 判断因为下面的mapfile 我只是用来做共享内存,并不是真的需要文件读写,这个文件只是可有可无保存最后一次的内容而已
// 创建文件映射内核对象
HANDLE hMapFile = CreateFileMapping(
hFile,//INVALID_HANDLE_VALUE, // 物理文件句柄
NULL, // 默认安全级别
PAGE_READWRITE, // 可读可写
0, // 高位文件大小
BUF_SIZE, // 低位文件大小
mappingName // 共享内存名称
);
//将文件映射对象 映射到当前应用程序的地址空间
char *pBuf = (char *)MapViewOfFile(
hMapFile, // 共享内存的句柄
FILE_MAP_WRITE,//FILE_MAP_ALL_ACCESS, // 可读写许可
0,
0,
BUF_SIZE
);
while (1)
{
std::cout << "input..." << std::endl;
char szInfo[BUF_SIZE] = { 0 };
std::cin.getline(szInfo, BUF_SIZE);
std::cin.clear();//恢复输入
strncpy_s(pBuf, BUF_SIZE, szInfo, BUF_SIZE - 1);
pBuf[BUF_SIZE] = '\0';
}
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
CloseHandle(hFile);
return 0;
}
#include "pch.h"
#include <iostream>
#include <windows.h>
using namespace std;
#define BUF_SIZE 1024
TCHAR mappingName[] = TEXT("NameOfMappingObject"); // 共享内存的名字
int main()
{
// 可以不用createfilemapping 可以用openfilemapping 但是你要确保这个映射句柄已经被创建
HANDLE hMapFile = OpenFileMapping(FILE_MAP_READ, TRUE, mappingName);
if (hMapFile == NULL)
{
printf("open file map error!");
return 0;
}
char *pBuf = (char *)MapViewOfFile(
hMapFile, // 共享内存的句柄
FILE_MAP_READ, //FILE_MAP_ALL_ACCESS, // 可读写许可
0,
0,
BUF_SIZE
);
while (1)
{
cout << "收信息..." << endl;
getchar();
cout << pBuf << endl;
}
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
return 0;
}
Linux的内存映射
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
int main(){
int fd = open("test.txt",O_CREATE|O_READ,0644);
if (fd<0) {
perror("open error");
return 0;
}
int len = ftruncate(fd,4); //改变文件大小
if (len==-1){
perror("ftruncate error");
return 0;
}
char * p = mmap(NULL,len,PROT_READ,PROT_WRITE,MAP_SHARED,fd,0);//MAP_SHARED可以共享,MAP_PRIVATE不能共享
if (p==MAP_FAILED){
perror("mmap error");
return 0;
}
close(fd);
pid_t = fork();//开个子进程,懒得写2个了
if (pid==0)
{
//strcpy(p,"abc");//写数据
*p = 2000;
printf("*p = %d",*p);
}else if (pid>0){
sleep(1);
printf("*p = %d",*p);
}
munmap(p,len);
return 0;
}