Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 使用mremap重新分配内存_C_Linux_Memory Management - Fatal编程技术网

C 使用mremap重新分配内存

C 使用mremap重新分配内存,c,linux,memory-management,C,Linux,Memory Management,我试图使用malloc分配两个不同的4096字节,并用不同的值初始化这些分配。之后,我希望其中一个指针指向另一个分配,“不”更改p1的值,“不”复制数据。我想将第二个分配“重新映射”到第一个分配,这将基本上更改流程页表中的虚拟地址,即不涉及复制。当我运行这段代码时,我发现mremap失败了。你知道如何做到这一点吗 int main(){ char *p1 = (char *)malloc(4096); memset(p1, 'a', 4096); char *p2 = (

我试图使用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;
}
预期产出: p1是位于xxx的地址 p2是地址yyy处的b
p0在地址xxx处为b

malloc()
返回的地址可能没有页面对齐,因此
mremap()
正在将
errno
设置为
EINVAL
。如果我使用
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;
}

malloc()
返回的地址可能没有页面对齐,因此
mremap()
正在将
errno
设置为
EINVAL
。如果我使用
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;
}

从手册页:“如果指定了MREMAP_FIXED,则还必须指定MREMAP_MAYMOVE。”是否可能需要按位&而不是|?@cecilg23:它们都已指定。按位
|
组合位标志是正确的-按位
通常会为您提供零。从手册页:“如果指定了MREMAP_FIXED,那么还必须指定MREMAP_MAYMOVE。”是否可能需要按位&而不是|?@cecilg23:它们都是指定的。按位
|
组合位标志是正确的-按位
&
通常为零。谢谢。快速提问,在释放(取消映射)p1之前,怎么可能重新映射到p1?因为C让你做各种事情。我不一定推荐这是个好主意,只是使用
mmap()
作为获取页面对齐地址的方便方法。hmmm所以这基本上覆盖了p1指向的虚拟页面的页面表条目和p2指向的物理页面。我懂了。谢谢。这真的很有帮助。你必须重新映射,而不必先取消映射那里的内容,除非你对程序中运行的每一段代码都有高度的控制。如果先取消映射,地址范围将不再属于您,并且您可能会在以后执行重新映射时删除分配的其他内容。谢谢。快速提问,在释放(取消映射)p1之前,怎么可能重新映射到p1?因为C让你做各种事情。我不一定推荐这是个好主意,只是使用
mmap()
作为获取页面对齐地址的方便方法。hmmm所以这基本上覆盖了p1指向的虚拟页面的页面表条目和p2指向的物理页面。我懂了。谢谢。这真的很有帮助。你必须重新映射,而不必先取消映射那里的内容,除非你对程序中运行的每一段代码都有高度的控制。如果首先取消映射,地址范围将不再属于您,并且您可能会在以后执行重新映射时删除分配的其他内容。