从传令上看,我的印象是
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访问该空间时没有反映出来:
/* 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;
}
编辑:它在更改时起作用。
segment = mremap(physicalMems[i], physicalSize, physicalSize,
MREMAP_MAYMOVE | MREMAP_FIXED | MREMAP_DONTUNMAP, segment);
至
physicalMems[i] = mremap(physicalMems[i], physicalSize, physicalSize,
MREMAP_MAYMOVE | MREMAP_FIXED, segment);
但我还是不明白为什么。
发布于 2022-09-11 21:01:11
网页上写着
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。
https://stackoverflow.com/questions/73205825
复制相似问题