【问题标题】:Can a memory page be moved by modifying the page table?可以通过修改页表来移动内存页吗?
【发布时间】:2011-02-10 08:47:19
【问题描述】:

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

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

【问题讨论】:

    标签: copy swap tlb


    【解决方案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;
    }
    

    【讨论】:

    • 这正是我所需要的。谢谢亚当!
    【解决方案2】:

    我认为内存映射文件可以解决问题,但我想我自己从未尝试过。使用 mmap 和 MAP_ANONYMOUS 来映射纯虚拟地址(无物理文件支持)。然后,您可以将您的“文件”重新映射到 VA 的各个区域,从而获得有效的零拷贝语义。在 Windows 中,您可以使用 MapViewOfFile 和使用 CreateMapOfFile(INVALID_HANDLE_VALUE, ...) 创建的文件映射句柄,但请注意,在 NT 上,您无法控制重新映射的 目标(即新映射的 VA 地址是函数调用的输出),在 Linux 上,所需的地址被视为 提示

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

    【讨论】:

    • 这确实有效。在 Linux 上,mremap 可以移动 mmap 分配的页面。
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-19
      • 2017-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多