memcpy / memmove从源复制(复制数据)到源。是否存在将页面从一个虚拟地址移动到另一个虚拟地址而不进行源数据的实际逐字节复制的情况?对我来说似乎完全可能,但是任何操作系统实际上都允许这样做吗?对我来说,动态阵列是如此广泛和流行的概念似乎很奇怪,但通过物理复制来增长它们是一种浪费的操作。当你开始谈论千兆字节的数组大小时,它就不会扩展(例如,想象一下将100GB阵列增加到200GB阵列。这个问题完全可以在< $ 10K范围内的服务器上完成。
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)
答案 0 :(得分:6)
在某种程度上,你可以在Linux上使用mremap
来做到这一点。
该调用使用进程的页表进行零拷贝重新分配(如果可以)。在所有情况下都不可能(地址空间碎片,只是存在其他现有映射是一个问题)。
该手册页实际上是这样说的:
mremap()更改虚拟地址和内存页面之间的映射。这可用于实现非常有效的realloc(3)。
答案 1 :(得分:2)
是的,内存映射文件的常见用途是通过映射文件的不同视图来“移动”或复制内存之间的内存
答案 2 :(得分:1)
每个POSIX系统都能够做到这一点。如果您将mmap
与文件描述符(由open
或shm_open
获取)而不是匿名使用,则可以取消映射,然后截断(缩小或增大),然后再次映射。您可能并且经常会为相同的页面获取不同的虚拟地址。
答案 3 :(得分:0)
我的意思是,你永远无法绝对保证在接下来的100GB中没有活动内存,所以你可能无法使它连续。
另一方面,您可以使用一个参差不齐的数组(数组数组),其中数组不必彼此相邻(甚至相同的大小)。动态数组的许多优点可能无法扩展到100GB领域。