代码之家  ›  专栏  ›  技术社区  ›  Joe

达尔文真的没有MREMAP吗?

  •  15
  • Joe  · 技术社区  · 15 年前

    我想知道如何在Mac上重新映射内存映射文件(当我想扩展可用空间时)。

    我看到我们在Linux世界的朋友 mremap 但是在我的Mac的头文件中找不到这样的功能。 /Developer/SDKs/MacOSX10.6.sdk/usr/include/sys/mman.h 具有以下内容:

    • mmap
    • mprotect
    • msync
    • munlock
    • munmap
    • 但没有 多重映射

    man mremap 证实了我的恐惧。

    我现在不得不 蒙图 mmmap 如果我想调整映射文件的大小,这涉及到使所有加载的页面无效。一定有更好的办法。当然?

    我正在尝试编写可以在Mac OS X和Linux上工作的代码。如果我 但我宁愿做得恰当。

    4 回复  |  直到 8 年前
        1
  •  0
  •   jilles    15 年前

    您可以将文件ftrunate为大尺寸(创建一个孔),然后mmap所有文件。如果文件是持久的,我建议用写调用来填补这个漏洞,而不是通过在映射中写入,否则文件的块可能会在磁盘上不必要地碎片化。

        2
  •  5
  •   R.. GitHub STOP HELPING ICE    8 年前

    如果你需要缩小地图,只要 munmap 要删除的末端部分。

    如果你需要放大地图,你可以 mmap 适当的偏移量 MAP_FIXED 到旧地图上方的地址,但您需要小心,不要在已经存在的其他地址上映射…

    上面删掉的文字是一个糟糕的想法; MAPX固定 基本上是错误的,除非你已经知道目标地址是什么并且想要原子地替换它。如果您试图机会主义地映射新的内容,如果地址范围是空的,则需要使用 MMAP 带有请求的地址,但是 没有 MAPX固定 并查看它是否成功并给您请求的地址;如果成功但地址不同,您将希望取消映射刚刚创建的新映射,并假定不可能在请求的地址进行分配。

        3
  •  1
  •   Zan Lynx    14 年前

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

        4
  •  0
  •   Potatoswatter    15 年前

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

    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 . 但这两种方法都不能保证任何东西,另一方面,它也可能同样安全。