我正在练习使用 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;
};
我观察到的是,我的应用程序使用的物理内存随着读取操作而不是写入操作而逐渐增长!
也许我的理解是错误的?