使用 mremap 重新分配内存

Kee*_*eto 1 c linux memory-management

我正在尝试使用 malloc 分配两个不同的 4096 字节,并使用不同的值初始化这些分配。之后,我希望其中一个指针指向另一个分配,“不”更改 p1 的值并且“不”复制数据。我想将第二个分配“重新映射”到第一个分配,这基本上应该更改进程页表中的虚拟地址,即不涉及复制。当我运行此代码时,我发现 mremap 失败。知道如何实现这一点吗?

int main(){
    char *p1 = (char *)malloc(4096);
    memset(p1, 'a', 4096);
    char *p2 = (char *)malloc(4096);
    memset(p2, 'b', 4096);
    printf("p1 is %c at address %p\n", p1[0], p1);
    printf("p2 is %c at address &p\n", p2[0], p2);
    free(p1);
    /* remapping virtual addresses */
    void *p0 = mremap(p2, 4096, 4096, MREMAP_MAYMOVE | MREMAP_FIXED, p1);
    /* checking */
    printf("p0 is %c at address %p\n", p0[c], p0);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

预期输出: p1 是地址 xxx 处的 a p2 是地址 yyy 处的 b p0 是地址 xxx 处的 b

Cro*_*man 5

返回的地址malloc()可能不是页面对齐的,因此mremap()设置errnoEINVAL。如果我使用,mmap()代替malloc(), 并修复代码中的语法错误:

#define _GNU_SOURCE 1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>

int main(void) {
    char *p1 = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
                    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    memset(p1, 'a', 4096);

    char *p2 = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
                    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    memset(p2, 'b', 4096);

    printf("p1 is %c at address %p\n", p1[0], (void *)p1);
    printf("p2 is %c at address %p\n", p2[0], (void *)p2);

    void *p0 = mremap(p2, 4096, 4096, MREMAP_MAYMOVE | MREMAP_FIXED, p1);
    if ( p0 == MAP_FAILED ) {
        perror("mremap: mremap failed");
        return EXIT_FAILURE;
    }

    printf("p0 is %c at address %p\n", ((char *)p0)[0], p0);
    return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

然后我得到:

paul@local:~/src/c/scratch$ ./mremap
p1 is a at address 0x7f5addb71000
p2 is b at address 0x7f5addb70000
p0 is b at address 0x7f5addb71000
paul@local:~/src/c/scratch$ 
Run Code Online (Sandbox Code Playgroud)