达尔文真的没有mremap吗?

问题描述 投票:0回答:5

我正在尝试找出如何在 Mac 上重新映射内存映射文件(当我想扩展可用空间时)。

我看到Linux世界的朋友有

mremap
,但我在我的Mac上的标题中找不到这样的功能。
/Developer/SDKs/MacOSX10.6.sdk/usr/include/sys/mman.h
具有以下特点:

  • mmap
  • mprotect
  • msync
  • munlock
  • munmap
  • 但是没有
    mremap

man mremap
证实了我的恐惧。

如果我想调整映射文件的大小,我目前必须

munmap
mmmap
,这涉及使所有加载的页面无效。一定会有更好的办法。当然可以吗?

我正在尝试编写可在 Mac OS X 和 Linux 上运行的代码。如果我的话,我可以选择一个宏来在每种情况下使用最好的函数,但我宁愿正确地执行它。

c macos mmap memory-mapped-files libc
5个回答
4
投票

如果需要缩小地图,只需

munmap
要删除末尾的部分即可。

如果您需要放大地图,您可以使用

mmap
MAP_FIXED
到旧地图上方的地址进行适当的偏移,但您需要小心,不要映射到已经存在的其他内容上。 ..

上面的删除线文本是一个糟糕的主意;

MAP_FIXED
从根本上来说是错误的,除非您已经知道目标地址上有什么并且想要自动替换它。如果您在地址范围空闲的情况下尝试机会性地映射新内容,则需要将
mmap
与请求的地址一起使用,但 不使用
MAP_FIXED
并查看是否成功并为您提供所请求的地址;如果成功但使用不同的地址,您将需要取消映射刚刚创建的新映射,并假设无法在请求的地址进行分配。


1
投票

如果您扩展足够大的块(例如,64 MB,但这取决于它增长的速度),那么使旧地图失效的成本可以忽略不计。一如既往,在假设问题之前进行基准测试。


0
投票

您可以将文件截断为大尺寸(创建一个洞)并映射所有文件。如果文件是持久的,我建议使用写入调用来填充漏洞,而不是通过写入映射来填充,否则文件的块可能会在磁盘上产生不必要的碎片。


0
投票

我没有内存映射经验,但看起来您可以临时将同一个文件映射两次,作为扩展映射而不丢失任何内容的方法。

int main() {
    int fd;
    char *fp, *fp2, *pen;

      /* create 1K file */
    fd = open( "mmap_data.txt", O_RDWR | O_CREAT, 0777 );
    lseek( fd, 1000, SEEK_SET );
    write( fd, "a", 1 );

      /* map and populate it */
    fp = mmap( NULL, 1000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
    pen = memset( fp, 'x', 1000 );

      /* expand to 8K and establish overlapping mapping */
    lseek( fd, 8000, SEEK_SET );
    write( fd, "b", 1 );
    fp2 = mmap( NULL, 7000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );

      /* demonstrate that mappings alias */
    *fp = 'z';
    printf( "%c ", *fp2 );

      /* eliminate first mapping */
    munmap( fp, 1000 );

      /* populate second mapping */
    pen = memset( fp2+10, 'y', 7000 );

      /* wrap up */
    munmap( fp2, 7000 );
    close( fd );
    printf( "%d\n", errno );
}

输出是

zxxxxxxxxxyyyyyy....

我想,如果你继续这样做,可能会比使用

mremap
更快地耗尽地址空间。但无论如何都无法保证,但另一方面它也可能同样安全。


0
投票

你可以看看 mach_vm_remap

© www.soinside.com 2019 - 2024. All rights reserved.