使用单个写操作写入多个VA位置

Writing to multiple VA locations with a single write operation

本文关键字:VA 位置 单个写 操作      更新时间:2023-10-16

我正在编写一个带有黑盒库的接口(称之为" a "),并且需要传递给它一个void*分配。我想用来自其他两个库(称为"X"answers"Y")的两个单独的分配来支持这个分配,将所有写操作复制到两个分配中。实际上,我希望将所有写操作"分叉"到两个现有的VA范围。诀窍在于这些分配可能非常大,但只稀疏地写入几个字节,因此不能复制整个分配。目前,我正在使用写监视内存和我自己创建的第三个分配来完成这个任务,但是有没有更有效的方法来做到这一点?或者,是否有一种方法可以将添加 write-watch属性到由库X或库Y创建的现有分配中?

基本上,这就是我今天要做的(半伪代码):
void* x = LibraryX.Allocate(size);
void* y = LibraryY.Allocate(size);
void* a = VirtualAlloc(size, WRITE_WATCH);
LibraryA.WriteSomeStuffToRandomLocations(a);
addresses = GetWriteWatch(a);
for(auto p : addresses)
{
    memcpy(x, p, size);
    memcpy(y, p, size);
}

理想情况下,我可以有这样的东西:

void* x = LibraryX.Allocate(size);
void* y = LibraryY.Allocate(size);
void* a = GetVARangeThatDuplicatesAllWritesTo(x, y);
LibraryA.WriteABunchOfStuff(a);

如果这些外部库正在分配内存,那么您就无能为力了。如果您控制分配和格式,您可以使用VirtualProtect使两个地址指向相同的物理内存位置。如果数据稀疏,这将特别有吸引力,因为您只能在需要时提交页面。

所以简短的回答是"不是那种设计。"

我建议你仔细检查WriteWatch的成本,以及它被触发的频率。您可能会对最终调用memcpy()的费用和次数感到惊讶。

如果您可以自己控制物理分配,则可以使两个虚拟地址指向同一个物理页。然而,没有办法采取两个物理页,使它们相同,因为你的LibraryY和LibraryX大概分配正常的虚拟内存,有它自己的独特的物理页,为每个分配(换句话说,内存分配是完成类似HeapAlloc, malloc, realloc, c++的new和其他这样的函数)。