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

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

  • mmap
  • mprotect
  • msync
  • munlock
  • munmap
  • 但不是 mremap

man mremap 确认我的恐惧。

我目前必须 munmapmmmap 如果我想调整映射文件的大小,这涉及使所有加载页面无效。肯定有更好的办法。一定?

我正在尝试编写将在Mac OS X和Linux上使用的代码。如果我 但是,我宁愿做得正确。

有帮助吗?

解决方案

您可以将文件输入到一个大尺寸(创建一个孔)中,并将所有文件mmap mmap。如果文件持续存在,我建议用写入呼叫来填充孔,而不是通过在映射中写入孔,否则文件的块可能会在磁盘上不必要地分散。

其他提示

如果您需要收缩地图,只是 munmap 您要删除的零件。

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

上面的三振出局是一个可怕的主意。 MAP_FIXED 从根本上是错误的,除非您已经知道目标地址是什么并希望在原子上取代它。如果您试图在地址范围免费的情况下进行机会绘制新的东西,则需要使用 mmap 带有请求的地址 没有 MAP_FIXED 看看它是否成功并为您提供请求的地址;如果成功,但是有了不同的地址,您将需要拆除您刚刚创建的新映射,并假设无法在请求的地址分配。

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

我没有内存映射的经验,但是看起来您可以暂时将同一文件映射为两次,以扩展映射而不会丢失任何东西。

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. 。但是,无论哪种方式都没有保证,另一方面可能同样安全。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top