2017-10-19 115 views
0

我承认,这是一个只是没有点击我的主题的作业,所以更多的解释集中回答将不胜感激。无法将我的共享内存的名称写入管道

我想为我的多个其他进程创建共享内存,以便能够访问给定共享内存的名称。我的其他进程通过管道连接到父进程,我想在共享内存的名称创建后写入管道。这是我的代码到目前为止。我从来没有能够做到这一点。

当我写出注释时,该程序将工作一次。但是,当我尝试再次运行该程序时,我需要更改名称空间的名称以使其正常工作。我不明白为什么会这样。我确定有一个我不明白的功能之一。

int shm; 
    char *p; 
    shm = shm_open("Name", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); 
    size_t len = 4 * 255; 

    if (ftruncate(shm, len) == -1) { 
    perror("Truncate"); 
    return 1; 
    } 

    p = mmap(0, 4, PROT_WRITE, MAP_SHARED, shm, 0); 
    if (p == MAP_FAILED){ 
    perror("mmap"); 
    return 1; 
    } 

    write(fd[1], "Name", 30); 

    printf("Initiator: Shared memory for Consonanats is %d.\n", shm); 
+0

任何打开的资源在完成后都应该关闭。你应该'shm_close'你的共享内存。每次重新运行程序时,这可能会摆脱改变命名空间的需要。 – Hypino

+0

共享内存段的名称应该以斜杠('/')开头。 –

+0

@Hypino,你好像拼错了“'shm_unlink'”。没有'shm_close()',至少不是'shm_open()'的标准对应物。 –

回答

0

write()调用的参数不一致:

write(fd[1], "Name", 30); 

您正在尝试写30个字节的5字节数组,这显然超支数组边界的。

此外,您没有检查您的write()呼叫的返回值。原则上,可能会发生短暂写入,因此您需要进行一次或多次其他调用来传输其余字节。也许更可能的是,写作可能会完全失败,在这种情况下,您可能想要注意并做一些事情。任何一种情况都会通过write()的返回值发出信号。

此外,你写的:

当我尝试再次运行该程序,我需要改变我的 名字空间的名字为它工作。我不明白为什么会这样。 我确信有这些功能之一的属性我不知道 。

是的,肯定有一个属性你不明白:共享内存段有内核范围和持久性。除此之外,这意味着他们的一生不限于创造他们的过程,而且他们的名字对系统而言是全球性的。这就是为什么不同的进程可以通过指定相同的名称来获得对同一段的访问。

正如@Hypino在评论中所看到的,您永远不会删除您创建的细分受众群。事实上,你不能直接这样做;相反,您必须通过shm_unlink()取消的链接。这将段的名称与内核分离,但不直接销毁它。这是不安全的,因为其他进程(甚至是同一进程)可能仍然在使用它。在被解除链接之后,该细分市场将准备好拆除和移除,但这只会在没有更多流程映射时才会发生。同时,可以创建具有给定名称的不同分段。

因此,通常的做法是在共享内存段安全实用时尽快断开链接。实际上,这意味着在需要映射它的所有进程(通过名称)之后,尽快完成此操作。段映射是每个进程的属性,所以它们在进程退出时消失。

但实际上,目前尚不清楚为什么重复使用名称会导致麻烦。除非在标志中指定了O_EXCL,否则应该能够打开先前运行中剩余的现有共享内存段。我怀疑这个特定的问题涉及到你省略的代码。

另外,关于细分名称,请注意您命名选择的自由并不是绝对的。作为Linux手册shm_open()所说:

对于便携式应用,共享存储器对象应由形式/somename的 名称来识别;即由最初的 斜线组成的最多为NAME_MAX(即255个)字符的以NULL结尾的字符串,后跟一个或多个字符,其中没有一个是斜杠。

+0

你比我的教授在整个演讲中多教了我三段,非常感谢!不胜感激。 – user4493284