可以通过修改页面表来移动内存页面吗?

问题描述:

是否可以(在任何合理的操作系统上,最好是Linux上)通过修改页表而不是实际移动任何数据来交换两个内存页的内容?可以通过修改页面表来移动内存页面吗?

动机是一种密集的矩阵转置。如果数据被页面​​大小阻塞,则可以在页面内调换数据(适合缓存),然后交换页面以将块移动到最终位置。一个大的矩阵会有很多页面移动,所以希望刷新TLB不会造成麻烦。

我认为内存映射文件可能会诀窍,但我认为我从来没有尝试过这一点。使用mmap与MAP_ANONYMOUS映射到纯虚拟地址(不支持物理文件)。然后,您可以将您的'文件'重新映射到VA的各个区域,以实现零拷贝语义。在Windows中,您将使用MapViewOfFile以及使用CreateMapOfFile(INVALID_HANDLE_VALUE,...)创建的文件映射句柄,但是注意比在NT上无法控制重新映射的目标(即,新映射的VA地址是输出函数调用的),并且在Linux上,期望的地址被认为是提示

如果这不起作用,那么你可能需要在内核中创建一个内存管理器模块,这对任何实际项目都是不可行的。

+0

这工作正好。 Linux mremap上的 可以移动由mmap分配的页面。 – Adam 2010-04-21 04:41:18

理论上肯定。实际上,我认为认为您可以使用mmap()以这种方式移动系统V风格的共享内存块。

#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; 
} 
+0

这正是我所需要的。感谢Adam! – feradz 2015-08-11 15:18:38