简述
在Windows中,在同一台机器上数据共享的最底层机制就是内存映射文件。在我们处理较大文件的时候,通常需要使用文件映射,即将物理地址中的文件数据映射到进程的虚拟地址中。通过文件映射之后,可以像操作内存一样去直接操作文件,而不需要再调用文件读写方法了。内存映射文件可以用于这几个不同的目的:
-
系统使用内存映射文件,以便加载和执行. exe和DLL文件。这可以大大节省页文件空间和应用程序启动运行所需的时间。
-
可以使用内存映射文件来访问磁盘上的数据文件。这使你可以不必对文件执行I/O操作,并且可以不必对文件内容进行缓存。
-
可以使用内存映射文件,使同一台计算机上运行的多个进程能够相互之间共享数据。Windows确实提供了其他一些方法,以便在进程之间进行数据通信,但是这些方法都是使用内存映射文件来实现的,这使得内存映射文件成为单个计算机上的多个进程互相进行通信的最有效的方法。
代码之路
#include <QCoreApplication>
#include <QFile>
#include <iostream>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QFile file("777.txt");
file.open(QIODevice::ReadWrite);
std::cout << "内存大小:" << file.size() << std::endl;
uchar *fpr = file.map(0, file.size()); //这里把文件里的内容映射到虚拟内存中,fpr就是首地址
//注意这里的file.size()如果大于系统的虚拟内存,就要对文件分块映射
//如果是读大文件,一般都是进行分块映射的
std::cout << "映射的文件内容:" << std::endl;
for (int i = 0; i < 9; ++i) {
std::cout << char(fpr[i]);
}
std::cout << std::endl;
*fpr = 'a'; //可以直接写入,修改文件的内容
fpr[1] = 'b';
fpr[2] = 'c';
std::cout << "修改后的文件内容:" << std::endl;
for (int i = 0; i < 9; ++i) {
std::cout << char(fpr[i]);
}
file.unmap(fpr);
file.close();
return a.exec();
}
运行结果:
注意:
如果文本文件中有换行的话,输出的时候换行符是不会显示的,文本文件中的换行为'\r\n'。'\r'ASCII码为13 是回车,将当前位置移到本行头,'\n'ASCII码为10 是换行,将当前位置移到下一行。虽然输出字符是不显示,但是这两个是会占用掉两个字节的地址的。
总结
上面讲的是如何进行文件映射,那我们如何实现进程间通信呢?首先,我们在第一个进程中通过上面的方法建立文件映射对象,然后通过其它IPC机制(有名管道、邮件槽等)把获得的映射到的对象句柄传递给第二个进程。第二个进程复制该句柄就取得对该文件映射对象的访问权限。
文件映射流程: