使用共享内存以及如何正确取消分配 space 和 IPC_RMID

Using shared memory and how to correctly unallocate a space with IPC_RMID

我的 linux 盒子上有 2 个应用程序 运行,一个服务器和一个客户端。我正在使用的服务器和客户端示例来自 Dave Marshalls examples.

一切正常,但是当我在我的后台进程中尝试这个并且我想扩展我的原始段时(可能由于将来的应用程序升级)我要么必须更改我的密钥要么以某种方式通过 shmctl(shmid, IPC_RMID, 0) 调用我的应用程序。由于我的应用程序无法优雅地退出,并且我无法在分配后一开始就设置它(因为一旦它被标记为删除,其他应用程序将无法使用此共享内存 space)我无法清理它space up.

到目前为止我想出的最好的方法是 shmget 我的旧部分,检查它是否存在,如果存在则清除它然后将它分配给一个高值。这看起来像:

void init_shared_mem(void)
{
    int shmid;
    key_t key = 0x1235; //key to be passed to shmget()
    int oldSize = 27;
    int newSize = 28;
    char * shm;

    //check to see if an allocation exists
    if ((shmid = shmget(key, oldSize, IPC_CREAT | 0666)) < 0)
    {
        perror("shmget: shmget failed");
    }
    //unallocate it if it does
    else if (shmctl(shmid , IPC_RMID , 0) == -1)
    {
        perror("shmid");
    }


    //reallocate new section
    if ((shmid = shmget(key, newSize, IPC_CREAT | 0666)) < 0)
    {
        perror("shmget: shmget failed");
        exit(1);
    }

    if ((shm = shmat(shmid, NULL, 0)) == (char *) -1)
    {
        perror("shmat");
        exit(1);
    }
}

其他 SO 问题似乎没有涉及此问题或将其作为可能的问题提出。有没有更好的方法来做到这一点,我错过了,或者我可以简单地将它重新分配到更高的值而不是清除它?

您没有说明您 运行 使用的是哪个操作系统。如果你在 Linux, OpenBSD 5.1 or later or other operating systems configured a particular way you may well be able to attach after having done IPC_RMID so long as something is still attached to it but bear in mind this behaviour is not portable (here's an older examination of IPC_RMID behaviour on different OSes)。没有这种行为,如果您的程序崩溃(又名 "doesn't exit graciously"),当它是附加到该段的最后一个东西时,将很难避免遗留陈旧的段。

我还应该注意到,您的问题听起来与 UNIX 套接字常见问题解答论坛 Options for robust process cleanup 中讨论的问题相似,其中的建议包括:使用 Linux 的 IPC_RMID 行为, 让监控父进程检查进程是否死亡并进行清理。