在Mac OS X上实现使用mmap的写时复制缓冲区

6
我一直在尝试 Linux 上的写时复制缓冲区,以下示例似乎按预期工作:
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

#define SIZE 4096

#define SHM_NAME "foobar"

int main(void)
{
    int fd = shm_open(SHM_NAME, O_RDWR | O_CREAT, 0666);
    int r = ftruncate(fd, SIZE);

    char *buf1 = mmap(NULL, SIZE, PROT_READ | PROT_WRITE,
                     MAP_SHARED, fd, 0);

    strcpy(buf1, "Original buffer");

    char *buf2 = mmap(NULL, SIZE, PROT_READ | PROT_WRITE,
                      MAP_PRIVATE, fd, 0);

    // At this point buf2 is aliased to buf1

    // Now modifying buf2 should trigger copy-on-write)...

    strcpy(buf2, "Modified buffer");

    // buf1 and buf2 are now two separate buffers

    strcpy(buf1, "Modified original buffer");

    // clean up

    r = munmap(buf2, SIZE);
    printf("munmap(buf2): %i\n", r);
    r = munmap(buf1, SIZE);
    printf("munmap(buf1): %i\n", r);
    r = shm_unlink(SHM_NAME);
    printf("shm_unlink: %i\n", r);

    return EXIT_SUCCESS;
}

然而,在OS X(10.10)下,第二个mmap调用返回MAP_FAILED,并且errno = 22(EINVAL)。OS X mmap手册页面似乎表明这应该可以工作(它甚至在MAP_PRIVATE标志的描述中提到了写时复制),我已经尝试使用各种不同的标志调用mmap,但是没有什么有效。有什么想法吗?


OS X 上使用 MAP_PRIVATE 时,无法处理文件描述符。 - l'L'l
请在这里查看。 - l'L'l
好的 - 谢谢 - 我会试一下。我不确定它是否有帮助,因为我正在尝试获取一个最初别名为 MAP_SHARED 缓冲区的 MAP_PRIVATE 缓冲区,然后通过写时复制重新映射。所以我认为 offset 对于两者都需要为0,但我准备尝试任何东西。;-) - Paul R
1
这里有一个使用 open 的示例;似乎使用 shm_open 并使用 MAP_SHAREDMAP_PRIVATE 进行别名处理会影响文件描述符。从外观上看,这可能是一个错误。 - l'L'l
2
太棒了 - 我刚刚尝试使用普通文件而不是shm_open,现在一切都正常了!非常感谢您的帮助 - 如果您愿意,可以将此写成答案,我会点赞/接受它,否则我稍后会为可能将来遇到相同问题的任何人自己完成。 - Paul R
显示剩余3条评论
1个回答

5

使用 shm_openMAP_SHAREDMAP_PRIVATE 似乎会导致文件描述符产生不良影响。使用 open 是一种可能的解决方法:

int fd = open(SHM_NAME, O_RDWR | O_CREAT, 0666);
...

结果:

munmap(buf2): 0
munmap(buf1): 0
shm_unlink: -1

使用 shm_openMAP_SHAREDMAP_PRIVATE 结果会导致一个 Invalid file descriptor,但是使用 MAP_SHAREDMAP_SHARED 则不会产生此问题。我不确定这是否是一个错误或者是设计如此 - 这种行为似乎并不正确。


2
谢谢 - 使用普通文件从shm_open切换到open解决了我的问题! - Paul R

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接