我的问题如下:
我 mmap (内存映射)将文件放入虚拟内存空间。 当我第一次使用指针访问文件的第一个字节时,操作系统将尝试访问内存中的数据,但它会失败并引发页面错误,因为现在数据不存在于内存中。因此操作系统会将数据从磁盘交换到内存中。最后,我的访问将成功。
(问题即将来临) 当我修改数据(内存中)并写回磁盘文件时,我怎么能释放物理内存供其他人使用,但是保留虚拟内存以便根据需要将数据提取回内存? 这听起来像操作系统知道内存耗尽的页面输出和页面调整行为,它会将LRU(或类似的东西)内存页面交换到磁盘(交换文件)并释放物理内存用于其他进程,以及根据需要将被驱逐的数据提取回内存。但这种机制由操作系统控制。
由于某些原因,我需要自己控制页面调出和页面调整行为。那我该怎么办?破解内核?
答案 0 :(得分:1)
您可以使用madvise
系统调用。它的行为受advice
参数的影响;有很多建议选择,应根据申请的具体情况选择最佳建议。
标志MADV_DONTNEED
意味着应该无条件地释放给定范围的物理支持帧(即,被分页)。也:
成功
MADV_DONTNEED
操作后,语义为 更改指定区域中的内存访问:后续 对范围内页面的访问将成功,但会产生 从最新的重新填充内存内容 底层映射文件的内容(用于共享文件) 映射,共享匿名映射和基于shmem 诸如System V共享内存段之类的技术)或零 匿名私有映射的按需填充页面。
如果你绝对确定它会非常长,直到你再次访问同一个位置,这可能会很有用。
然而,可能没有必要强制内核实际页面输出;相反,另一种可能性是,如果您按顺序访问映射,则使用madvise
和MADV_SEQUENTIAL
告诉内核您主要按顺序访问内存映射:
按顺序排列页面引用。 (因此,可以提前积极地读取给定范围内的页面,并且可以在访问它们后立即释放它们。)
或MADV_RANDOM
以随机顺序预期页面引用。 (因此,预读可能没有通常那么有用。)
这些并不像明确调用MADV_DONTNEED
页面那样具有攻击性。 (当然你也可以将它们与MADV_DONTNEED
结合起来)
在最近的内核版本中,还有the MADV_FREE
flag可以懒得释放页面框架;如果有足够的内存可用,它们将保持映射状态,但如果内存压力增大,内核将回收它们。
答案 1 :(得分:0)
你可以用mlock + munlock来锁定/解锁页面。这将使您可以控制被换出的页面。
您需要具有CAP_IPC_LOCK功能才能执行此操作。