【问题标题】:Does any OS allow moving memory from one address to another without physically copying it?是否有任何操作系统允许将内存从一个地址移动到另一个地址而不进行物理复制?
【发布时间】:2012-01-26 23:27:36
【问题描述】:

memcpy/memmove 从源到目标重复(复制数据)。是否存在将页面从一个虚拟地址移动到另一个而不对源数据进行实际逐字节复制的方法?对我来说这似乎是完全可能的,但是任何操作系统实际上都允许这样做吗?在我看来,动态数组是一个如此广泛和流行的概念,但通过物理复制来增长它们是一种非常浪费的操作,这对我来说似乎很奇怪。当您开始谈论以千兆字节为单位的数组大小时,它只是无法扩展(例如,想象将一个 100GB 的数组增加到一个 200GB 的数组。现在在

void* very_large_buffer = VirtualAlloc(NULL, 2GB, MEM_COMMIT);
// Populate very_large_buffer, run out of space.
// Allocate buffer twice as large, but don't actually allocate 
// physical memory, just reserve the address space.
void* even_bigger_buffer = VirtualAlloc(NULL, 4GB, MEM_RESERVE);
// Remap the physical memory from very_large_buffer to even_bigger_buffer without copying
// (i.e. don't copy 2GB of data, just copy the mapping of virtual pages to physical pages)
// Does any OS provide support for an operation like this?    
MoveMemory(very_large_buffer, even_bigger_buffer, 2GB)
// Now very_large_buffer no longer has any physical memory pages associated with it
VirtualFree(very_large_buffer)

【问题讨论】:

    标签: c++ c windows linux operating-system


    【解决方案1】:

    在某种程度上,您可以在 Linux 上使用 mremap 做到这一点。

    该调用使用进程的页表进行零拷贝重新分配如果可以的话。并非在所有情况下都是可能的(地址空间碎片,以及其他现有映射的存在只是一个问题)。

    手册页实际上是这样说的:

    mremap() 更改虚拟地址和内存页面之间的映射。这可用于实现非常高效的 realloc(3)。

    【讨论】:

    • 这看起来正是我想要的。我可以在 linux 上使用它,在其他地方使用标准的哑内存副本。
    • 或一个 realloc 并希望它在后台使用类似的方法。 :)
    【解决方案2】:

    是的,内存映射文件的常见用途是通过映射文件的不同视图在进程之间“移动”或复制内存

    【讨论】:

      【解决方案3】:

      每个 POSIX 系统都能够做到这一点。如果您将mmap 与文件描述符(由openshm_open 获得)一起使用并且不是匿名的,您可以取消映射它,然后截断(缩小或增长)然后再次映射它。您可能并且经常会为相同的页面获得不同的虚拟地址。

      【讨论】:

      • 如果我错了,请纠正我,但取消映射会将所有脏页写回该文件(懒惰?)所以当你重新映射它时,访问页面可能需要从文件中读取它们.那里有很多实现细节,但是通过导致磁盘 IO 来避免内存复制不太可能是一个胜利。不过我很好奇,因为 mmap 通常用于在进程之间共享内存,难道不应该在不关闭第一个映射的情况下增大(而不是缩小)文件并创建同一文件的第二个映射吗?我认为那将是一个零移动副本。
      • 首先,如果您使用shm_open,则没有文件,因此无法写入任何内容。即使对于open,我认为取消映射不会写回页面,只有关闭文件描述符才会强制执行。
      • 我猜在 shm_open 的情况下,您不会因为未映射而丢失内容,这很有趣。你是对的,我猜脏页不会因为你关闭映射而被写入,它应该仍然在系统写入缓冲区中。
      【解决方案4】:

      我的意思是,您永远无法绝对保证在接下来的 100GB 中没有活动内存,因此您可能无法使其连续。

      另一方面,您可以使用不规则数组(数组的数组),其中数组不必彼此相邻(甚至大小相同)。动态数组的许多优点可能无法扩展到 100GB 领域。

      【讨论】:

      • 我的理解是实际的物理 RAM 页面不必是连续的,这就是虚拟寻址的意义所在。但是您需要 200GB 的非分段虚拟地址空间(目前 64 位进程在现代操作系统中具有 8TB 的地址空间,所以这应该不是问题。)
      猜你喜欢
      • 1970-01-01
      • 2014-02-12
      • 1970-01-01
      • 2018-09-19
      • 2018-09-23
      • 1970-01-01
      • 1970-01-01
      • 2018-09-24
      • 2011-06-16
      相关资源
      最近更新 更多