首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >mremap实际上是做什么的?

mremap实际上是做什么的?
EN

Stack Overflow用户
提问于 2022-08-02 10:16:41
回答 1查看 173关注 0票数 1

从传令上看,我的印象是

代码语言:javascript
运行
复制
void *new_address = mremap(old_address, old_size, old_size, 
    MREMAP_MAYMOVE | MREMAP_FIXED | MREMAP_DONTUNMAP, new_address);

将new_address的虚拟地址空间映射到old_address映射到的物理地址空间。

但是,在我的测试程序中没有发生这种情况,因为通过old_address更改物理空间在通过new_address访问该空间时没有反映出来:

代码语言:javascript
运行
复制
/* The purpose of this program is to glue together physically allocated pieces of 
 * memory into a contiguous range of virtual addresses. */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <stdint.h>
#include <time.h>
#define __USE_GNU
#include <sys/mman.h>

/* Initializes numberOfSegments pieces of page-aligned memory of size 
 * physicalSize, where the ith segment is initialized to (char) i. */
void ** allocatePhysicalMem(int numberOfSegments, size_t physicalSize)
{
    void **physicalMems = malloc(numberOfSegments * sizeof(void *));

    for (int i = 0; i < numberOfSegments; i++) {
        physicalMems[i] = mmap(NULL, physicalSize, PROT_READ | PROT_WRITE,
                MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
        memset(physicalMems[i], (char) i, physicalSize);
    }

    return physicalMems;
}

void cleanup(void **physicalMems, size_t physicalSize, int numberOfSegments)
{
    for (int i = 0; i < numberOfSegments; i++) {
        munmap(physicalMems[i], physicalSize);
    }

    free(physicalMems);
}

int main()
{
    int numberOfSegments = 4;
    size_t physicalSize = 4096;
    size_t virtualSize = numberOfSegments * physicalSize;

    void *virtualMem = mmap(NULL, virtualSize, PROT_READ | PROT_WRITE,
                    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    void **physicalMems = allocatePhysicalMem(numberOfSegments, physicalSize);
    
    for (int i = 0; i < numberOfSegments; i++) {
        void *segment = (void *)((uintptr_t) virtualMem + i * physicalSize);
        segment = mremap(physicalMems[i], physicalSize, physicalSize, 
                MREMAP_MAYMOVE | MREMAP_FIXED | MREMAP_DONTUNMAP, segment);
        if (segment == MAP_FAILED) {
            perror("remapping failed");
            exit(EXIT_FAILURE);
        }
    }

    /* Expected output: a bunch of 0s, a bunch of 1s, ... */
    int stride = 2048;
    for (size_t i = 0; i < virtualSize; i += stride) {
        printf("%d", (int) ((char *)virtualMem)[i]);
    }
    printf("\n");

    for (int i = 0; i < numberOfSegments; i++) {
        memset(physicalMems[i], 0, physicalSize);
    }

    /* Expected output: a bunch of 0s */
    for (size_t i = 0; i < virtualSize; i += stride) {
        printf("%d", (int) ((char *)virtualMem)[i]);
    }
    printf("\n");

    cleanup(physicalMems, physicalSize, numberOfSegments);
    return EXIT_SUCCESS;
}

编辑:它在更改时起作用。

代码语言:javascript
运行
复制
segment = mremap(physicalMems[i], physicalSize, physicalSize, 
                MREMAP_MAYMOVE | MREMAP_FIXED | MREMAP_DONTUNMAP, segment);

代码语言:javascript
运行
复制
physicalMems[i] = mremap(physicalMems[i], physicalSize, physicalSize, 
                MREMAP_MAYMOVE | MREMAP_FIXED, segment);

但我还是不明白为什么。

EN

回答 1

Stack Overflow用户

发布于 2022-09-11 21:01:11

网页上写着

代码语言:javascript
运行
复制
After completion, any access to the range specified by
old_address and old_size will result in a page fault.  The
page fault will be handled by a userfaultfd(2) handler if
the address is in a range previously registered with
userfaultfd(2).  Otherwise, the kernel allocates a zero-
filled page to handle the fault.

在下面的https://man7.org/linux/man-pages/man2/mremap.2.html中,描述了MREMAP_DONTUNMAP标志,这意味着旧地址上的旧映射将被一个新的零填充页面所取代。如果您想在windows中使用mmap,可以使用https://github.com/CoderRC/libmingw32_extended中的my。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73205825

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档