0

我正在练习使用 Linux 的 Lazy Allocation 和 Demand Paging 策略。

我想要一个我分配的缓冲区,它不会mmap()占用物理内存,直到我真正向它写东西。此外,我希望它以 Linux 的交换页面大小(例如 4K)的步长逐渐扩大(使用更多物理内存),同时我从头到尾连续写入。

根据一些文档搜索,如果只有读取权限,它应该放大,但我在实验中观察到的现实不喜欢这样。

为了测试这一点,我编写了一个程序如下,并在top运行时通过 shell 命令观察内存状态。

constexpr size_t BUF_SIZE = 1024 * 1024 * 1024;

int main( int argc, char** argv ) {
    auto shm_pt = mmap( NULL, BUF_SIZE, PROT_READ | PROT_WRITE,
                        MAP_SHARED | MAP_ANONYMOUS, -1, 0 );
    if( shm_pt == MAP_FAILED ) {
        std::cerr << "mmap error:" << shm_pt;
        exit( EXIT_FAILURE );
    };

    bool full_zero = true;
    uint8_t* pc = reinterpret_cast<uint8_t*>( shm_pt );

    constexpr size_t STEP_SIZE = 1024 * 1024;
    for( size_t j = 0; j < BUF_SIZE / STEP_SIZE; ++j ) {
        this_thread::sleep_for( 100ms );
        size_t base = j * STEP_SIZE;
        std::cerr << "Reading from " << base / 1024 / 1024 << "M..." << endl;

        for( size_t i = 0; i < STEP_SIZE; ++i )
            full_zero = full_zero && pc[ base + i ] == 0;
    }

    if( !full_zero )
        std::cerr << "The buffer has not been initialized with full zeros!";

    for( size_t j = 0; j < BUF_SIZE / STEP_SIZE; ++j ) {
        this_thread::sleep_for( 100ms );
        size_t base = j * STEP_SIZE;
        std::cerr << "Writing to " << base / 1024 / 1024 << "M..." << endl;

        for( size_t i = 0; i < STEP_SIZE; ++i )
            pc[ base + i ] = 'c';
    }

    munmap( shm_pt, BUF_SIZE );
    return EXIT_SUCCESS;
};

我观察到的是,我的应用程序使用的物理内存随着读取操作而不是写入操作而逐渐增长!

也许我的理解是错误的?

4

1 回答 1

1

我知道了!

在我粘贴的搜索内容中,该人使用MAP_PRIVATE标志mmap()作为参数,而我使用MAP_SHARED.

看起来如果一个缓冲区在进程之间共享,一个 READING 操作也会导致真正的内存分配!

于 2022-01-28T04:07:33.357 回答