如何增加使用 mmap() 分配的内存区域的大小

How to increase the size of memory region allocated with mmap()

我正在使用 mmap Linux 系统调用分配内存。

        mov     x5, 0                   ; offset is zero
        mov     x4, -1                  ; no file descriptor
        mov     x3, 0x22                ; MAP_PRIVATE + MAP_ANONYMOUS
        mov     x2, 3                   ; PROT_READ + PROT_WRITE
        mov     x1, 4096                ; initial region size in bytes 
        mov     x0, 0                   ; let Linux choose region address
        mov     x8, 222                 ; mmap
        svc     0

是否可以在保留其起始地址和内容的情况下增加已分配内存区域的大小?如何正确操作?

如果您的原始区域后面有空闲虚拟地址 space,只需使用 MAP_FIXED | MAP_FIXED_NOREPLACE 标志和相同的权限在原始区域后面创建一个额外的映射区域。如果两个区域的页面大小相同,它们将合并为一个映射。

在 Linux 上,使用 mremap(2) Linux 特定的系统调用 而无需 MREMAP_MAYMOVE 扩展现有映射,不考虑将这些物理页面重新映射到不同的虚拟地址的选项,其中有足够的空间用于更大的映射。

如果您要扩展到的页面已经存在一些其他映射,它将 return 出错。 (与 mmap(MAP_FIXED) 不同,它会默默地替换那些映射。)

如果您正在用 asm 编写,那么对非 Linux 的可移植性几乎无关紧要;其他操作系统将有不同的调用号和 ABI,因此只需在 asm/unistd.h 中查找 __NR_mremap,然后从 sys/mman.h.

中获取 flags 模式

仅可移植 POSIX 调用,mmap() 具有非 NULL 提示地址 = 就在现有映射之后,但没有 MAP_FIXED;如果页面空闲,它将选择该地址(正如@datenwolf 所说,与早期映射合并到一个长范围内)。否则它会选择其他地方。 (然后你必须 munmap 最终不在你想要的位置的映射。)

有一个 Linux-特定的 mmap 选项:MAP_FIXED_NOREPLACE 将 return 一个错误,而不是映射到与提示不同的地址。早于 4.17 的内核不知道该标志,通常会将其视为除了 MAP_ANONYMOUS 之外没有使用其他标志,因此您应该根据提示检查 return 值。

不要使用MAP_FIXED_NOREPLACE | MAP_FIXED;这将在旧内核上充当 MAP_FIXED,也可能在知道 MAP_FIXED_NOREPLACE.

的新内核上充当

假设您知道要扩展的映射的起点以及所需的新总大小,mremap 是比 mmap(MAP_FIXED_NOREPLACE) 更好的选择。它至少从 Linux 2.4 开始支持,即几十年,并自动保留现有的映射标志和权限(例如 MAP_PRIVATE、PROT_READ|PROT_WRITE)

如果你只知道现有映射的结束地址,mmap(MAP_FIXED_NOREPLACE)可能是个不错的选择。