对 mmap MAP_PRIVATE 的更改对当前进程可见吗?

mmap 手册页告诉我们,对 MAP_PRIVATE 内存映射文件所做的内存更改是否对映射文件的进程可见是未指定的(它们不会写入映射文件,也不会对映射同一文件的其他进程可见)。

但是,我们可以使用此测试程序验证更改在任何给定系统/内核版本上是否实际可见:

mmap-private-check.cpp
#include <string>
#include <iostream>
#include <fstream>
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>
#include <sys/stat.h>

using namespace std;

int main() {
    string filename = "deleteme.txt";
    // 创建文件
    ofstream fout(filename.c_str());
    fout << "ABCD";
    fout.close();
    // 创建并打开底层文件
    int fd = open(filename.c_str(), O_RDONLY);
    assert(fd != -1);
    // 使用 MAP_PRIVATE 进行 mmap 并允许写入 mmap 的页面
    char* mmappedData = (char*)mmap(NULL, 4, PROT_WRITE, MAP_PRIVATE | MAP_POPULATE, fd, 0);
    assert(mmappedData != MAP_FAILED);
    // 将数据插入 MAP_PRIVATE 区域
    mmappedData[0] = 0;
    mmappedData[1] = 1;
    mmappedData[2] = 2;
    mmappedData[3] = 3;
    // 再次覆盖
    mmappedData[0] = 3;
    mmappedData[1] = 2;
    mmappedData[2] = 1;
    mmappedData[3] = 0;
    // 检查数据
    if(mmappedData[0] == 3 &&
        mmappedData[1] == 2 &&
        mmappedData[2] == 1 &&
        mmappedData[3] == 0) {
        cout << "恭喜,MAP_PRIVATE 更改反映在内存中!" << endl;
    } else {
        cout << "不,MAP_PRIVATE 更改未反映在内存中!" << endl;
    }
}

下载、编译并运行使用:

run-mmap-private-check.sh
wget https://techoverflow.net/scripts/mmap-private-check.cpp && g++ -o mmap-private-check mmap-private-check.cpp && ./mmap-private-check

这将打印

mmap-success.txt
Congrats, MAP_PRIVATE changes are reflected in memory!

(我在测试的每个 Linux 系统上只得到此结果,例如在 Ubuntu 18.04 上)或

mmap-fail.txt
Nope, MAP_PRIVATE changes are NOT reflected in memory!

注意此程序仅在写入数据后直接测试更改的可见性。原则上,内核允许在以后的任何时间点丢弃你的更改。所以请注意你在这里处于边缘,对 MAP_PRIVATE 内存进行更改本质上不安全,但实际上通常效果很好。


Check out similar posts by category: C/C++, Linux