是否可以(在任何合理的操作系统,最好是Linux上)通过修改页面表而不是实际移动任何数据来交换两个内存页面的内容?
动机是密集的矩阵转置。如果数据被页面大小阻止,则可以在页面中转置数据(适合缓存),然后交换页面以将块移动到最终位置。一个大矩阵会移动很多页面,所以希望刷新TLB不会造成麻烦。
答案 0 :(得分:1)
#include <stdio.h>
#include <string.h>
#define __USE_GNU
#include <unistd.h>
#include <sys/mman.h>
int main() {
int PAGE_SIZE = getpagesize();
char* m = NULL;
void* temp;
printf("page size = %d\n", PAGE_SIZE);
m = (char*)mmap(0, PAGE_SIZE*3, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
temp = m+PAGE_SIZE*2;
memset(m, '0', PAGE_SIZE);
memset(m+PAGE_SIZE, '1', PAGE_SIZE);
printf("before %c %c\n", m[0], m[PAGE_SIZE]);
mremap(m + PAGE_SIZE, PAGE_SIZE, PAGE_SIZE, MREMAP_FIXED | MREMAP_MAYMOVE, temp);
mremap(m, PAGE_SIZE, PAGE_SIZE, MREMAP_FIXED | MREMAP_MAYMOVE, m+PAGE_SIZE);
mremap(temp, PAGE_SIZE, PAGE_SIZE, MREMAP_FIXED | MREMAP_MAYMOVE, m);
printf("after %c %c\n", m[0], m[PAGE_SIZE]);
return 0;
}
答案 1 :(得分:0)
我认为内存映射文件可能会起作用,但我认为我自己从未尝试过。使用带有MAP_ANONYMOUS的mmap映射纯虚拟地址(无物理文件后备)。然后,您可以将“文件”重新映射到VA的各个区域,从而获得零拷贝语义。在Windows中,您将MapViewOfFile与使用CreateMapOfFile(INVALID_HANDLE_VALUE,...)创建的文件映射句柄一起使用,但请注意,在NT上,您无法控制重映射的目标(即。新映射的VA地址是函数调用的输出,在Linux上,所需的地址被视为提示。
如果这不起作用,那么你可能需要在内核中创建一个内存管理器模块,这对任何实际项目都是不可行的。
答案 2 :(得分:-1)
理论上,当然。在实践中,我认为你可以使用mmap()以这种方式移动系统V风格的共享内存块。