如何正确使用shm_open和mmap?涉及IT技术。

5

我正在尝试使用在网上找到的示例和文档创建共享内存区域。我的目标是IPC,以便我可以让不同的进程彼此通信。

这是我的C文件

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <errno.h>

int main (int argc, char *argv[])
{

struct stat sb;
off_t len;
char *p;
int fd;

fd = shm_open("test",  O_RDWR | O_CREAT); //,S_IRUSR | S_IWUSR);

if (fd == -1) {
    perror("open");
    return 1;
}

if (fstat(fd, &sb)==-1){
    perror("fstat");
    return 1;
}

/*if (!S_ISREG(sb.st_mode)){
    fprintf(stderr, "%s is not a file\n",fileName);
    return 1;
}*/

p = mmap(0, sb.st_size, PROT_WRITE, MAP_SHARED, fd, 0);
if (p == MAP_FAILED){
    perror("mmap");


    return 1;

}

if (close(fd)==-1) {
    perror("close");
    return 1;

}
for (len = 0; len < sb.st_size; len++) {
    putchar(p[len]);

}

if (munmap(p, sb.st_size) == -1) {
    perror("munmao");
    return 1;
}
fprintf(stderr,"\n");
return 0;
}

问题在于我收到了一个mmap:无效参数的错误提示。我猜测是fd出了问题,但是不知道如何解决,请大家帮忙。我使用的是最新版本的XCODE,电脑系统是Yosemite。

2个回答

5

您需要扩展共享内存映射的大小,至少在创建时第一次需要这么做。现在它的大小为0,mmap不允许您创建零长度的映射。

因此,您可以使用以下方式替换fstat()调用:

size_t len = 4096;
if (ftruncate(fd, len) == -1) {
    perror("ftruncate");
    return 1;
}

然后将此len传递给mmap()。


很抱歉,您的代码似乎无法正常运行,它给出了“ftruncate:Invalid argument”的错误提示。 - Kilon
1
好的,在Linux上它运行良好,但似乎OSX在shm_open/ftruncate方面有一些奇怪的行为,请参见https://dev59.com/uF8e5IYBdhLWcg3wqr2t(即你已经运行了程序多次,所以你需要先删除该段。此外,你的shm_open调用需要一个第三个参数,你已经注释掉了,hm_open("test", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);). - nos
谢谢你的帮助。我已经注释掉了那些部分,仅供测试目的。我甚至尝试过包含它们进行测试。我认为我会坚持使用open并避免使用shm_open,因为我决定我也想将我的共享内存作为备份存储到文件中,使用msync。 - Kilon

-4

你的addr参数被设置为0,这可能是保留值。你是否想使用NULL?这与0不同。


2
我也会给你点踩,因为在回答问题之前,你需要先了解一下 mmap 的工作原理。0 是 mmap 中最常用的地址,如果该地址已被占用,内核将会寻找一个空闲的地址。 - Kilon
NULL0,它们在这里的行为是相同的。 - ShadowRanger

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