在shm_unlink

时间:2016-01-17 16:47:04

标签: c linux embedded-linux

shm_unlink的操作对我来说不清楚。我创建了一个共享内存对象并映射到一个进程。后来,我对内存对象做了shm_unlink。在shm_unlink之后,我能够访问相同的内存进行读写。怎么可能?由于内存对象被shm_unlink破坏,我在这种情况下期待分段错误。但是,它没有发生?是什么原因? shm_unlink在这里做了什么?

以下是代码段。

main(int argc, char * argv[])
{
    int   fd;
    char  *addr;
    int i = 0;

    /*
    * In case the unlink code isn't executed at the end
    */
    if (argc != 1) {
        shm_unlink("/bolts");
        return EXIT_SUCCESS;
    }

    /* Create a new memory object */
    fd = shm_open("/bolts", O_RDWR | O_CREAT, 0666);
    if (fd == -1) {
        fprintf(stderr, "Open failed : %s\n",
            strerror(errno));
        return EXIT_FAILURE;
    }

    /* Set the memory object's size */
    if (ftruncate(fd, 1024) == -1) {
        fprintf(stderr, "ftruncate : %s\n", strerror(errno));
        return EXIT_FAILURE;
    }

    addr = mmap(0, 1024, PROT_READ | PROT_WRITE,
        MAP_SHARED, fd, 0);

    if (addr == MAP_FAILED) {
        fprintf(stderr, "mmap failed:%s\n", strerror(errno));
        return EXIT_FAILURE;
    }

    sleep(10);

    printf("Map addr is %x\n",(unsigned int) addr);

    if (fork())
    {
        sleep(10);
        strcpy (addr, "Sreehari in parent\n");
    }
    else
    {
        strcpy(addr,  "I am in child\n");

    }

    sleep(6);
    i = shm_unlink("/bolts");

    printf("addr is %s, i is %d \n", addr, i);
    return EXIT_SUCCESS;
}

3 个答案:

答案 0 :(得分:2)

shm_open / shm_unlink不会直接影响内存映射,必须使用相应的mmap / munmap-calls来完成。

shm_unlink从shm-filesystem中删除Posix共享内存段,如果删除了最后一个映射,则实际内存将被销毁。

答案 1 :(得分:1)

如shm_unlink man页面中所述:

  

“在shm_unlink()返回之前应删除该名称,但是内存对象内容的删除应推迟到   对共享内存对象的所有打开和映射引用都是   除去“。

这意味着取消链接后内存可能仍然存在。

答案 2 :(得分:1)

shm_open创建一个命名的共享内存对象。任何进程都可以使用传递给shm_open的名称映射该共享内存对象。 shm_unlink删除该名称,因此无法再映射共享内存区域,但实际内存在未映射之前是可用的。请注意,这类似于unlink:您可以在open()之后使用unlink() ed文件,并且在最后一个文件描述符为close() d之后将释放实际文件内容。

根据手册页:

  

shm_unlink()的操作类似于unlink(2):它删除了一个   共享内存对象名称,并且,一旦所有进程都取消映射   对象,取消分配和销毁关联的内容   记忆区域。成功shm_unlink()后,尝试   shm_open()具有相同名称的对象将失败(除非O_CREAT是   指定,在这种情况下创建一个新的,不同的对象。)