C Posix共享内存初始化
我的问题是关于初始化通过使用C Posix共享内存初始化,c,linux,unix,posix,shared-memory,C,Linux,Unix,Posix,Shared Memory,我的问题是关于初始化通过使用shm\u open()和mmap()获得的内存。我在几个地方看到的一个常见建议是使用标志调用shm_open():如果成功,那么我们是共享内存的第一个用户,可以初始化它,否则我们不是第一个,共享内存已经被另一个进程初始化 然而,从我对shm_open的理解以及我在Linux上所做的测试来看,这是行不通的:即使在共享内存对象的最后一个用户取消映射并关闭之后,共享内存对象仍会留在系统中。使用O|u create | O|u EXCL调用shm_open,然后关闭描述符并
shm\u open()
和mmap()
获得的内存。我在几个地方看到的一个常见建议是使用标志调用shm_open()
:如果成功,那么我们是共享内存的第一个用户,可以初始化它,否则我们不是第一个,共享内存已经被另一个进程初始化
然而,从我对shm_open
的理解以及我在Linux上所做的测试来看,这是行不通的:即使在共享内存对象的最后一个用户取消映射并关闭之后,共享内存对象仍会留在系统中。使用O|u create | O|u EXCL
调用shm_open
,然后关闭描述符并退出的简单测试程序将在第一次运行时成功,但在第二次运行时仍将失败,即使当时没有其他人使用共享内存
在我看来,(至少在我测试的系统上,shm_open
的行为与open()
:如果我修改我的简单测试程序,将一些东西写入共享内存(通过mmap
获得的指针)并退出,然后共享内存对象将持久地保存其内容(我可以运行另一个简单的程序来读回我以前写的数据)
那么,关于使用shm_open
和O|u create | O_EXCL
的建议是错误的,还是我遗漏了什么
我知道可以使用shm\u unlink()
删除共享内存对象,但这似乎只会导致更多问题:
shm\u unlink()
之前死亡,那么我们回到上面描述的问题shm_unlink()
,而其他一些进程仍映射到同一共享内存中,那么这些其他进程仍将一如既往地继续使用它。现在,如果另一个进程来调用具有相同名称的shm_open()
,并指定了O_create
,它将实际成功地创建具有相同名称的新共享内存对象,这与其他进程仍在使用的旧共享内存对象完全无关。现在,我们有一个进程试图通过共享内存与其他进程通信,但完全没有意识到它使用了错误的通道我习惯于Windows语义,其中共享内存对象只有在至少一个句柄打开时才存在,因此Posix的内容非常混乱。由于您使用
O_EXCL
标志,我将假设您有一组进程聚集在一个主进程(段的创建者)周围
然后,您的主进程将通过调用shm\u open
创建共享内存段:
shmid = shm_open("/insert/name/here", O_CREAT|O_EXCL, 0644);
if (-1 == shmid) {
printf("Oops ..\n");
}
在这里,从机已准备好使用该段。由于主机必须创建段,因此无需在从属调用中使用O_create
标志。如果在尚未创建或已销毁段时执行从属调用,则只需处理可能的错误
当您的任何进程对该段完成时,它应该调用shm\u unlink()
。在这种体系结构中,主人通常是在喂奴隶。当它没什么可说的时候,它就闭嘴了。然后,从机有责任优雅地处理相应的错误
如您所述,如果一个进程在调用shm\u unlink
过程之前死亡,那么该段将在此后继续存在。为了避免在某些情况下出现这种情况,您可以定义自己的信号处理程序,以便在接收到诸如SIGINT
之类的信号时执行该操作。无论如何,如果SIGKILL
被发送到您的进程中,您将无法覆盖混乱
编辑:
更具体地说,O|u CREAT | O_EXCL
的使用在不必要时是错误的。通过上面的一个小例子,您可以看到母版需要创建段,因此需要这些标志。另一方面,任何从属进程都不必创建它。因此,您将绝对禁止在相关调用中使用O_create
现在,如果另一个进程在已经创建段时调用shm_open(…,O_CREAT…)
,它将只检索与该段相关的文件描述符。因此,它将位于正确的频道上(如果它有权这样做,请参阅mode
参数)您可以执行以下操作:
int测试=shmget(键,大小,0);把它放在每个过程的起点。如果尚未创建现有共享内存,则此处的零标志尝试打开该内存。测试将等于-1,因此,如果测试-1转到并创建共享内存,则您可以在此语句后进行检查,否则您将获得现有共享内存的id。。。。。我希望这有助于看起来您在使用shm段时不会将其设置为删除。因此,它在您的过程中幸存下来。您可以在终端中使用
ipcs
命令来查看您的系统中当前有哪些类型的IPC内容(信号量、shm段等)。但是如何将其设置为删除?是否有要传递给shm_open()的标志?我在手册页上找不到任何内容。@Rerito:OP对您的评论有什么想法吗?在共享内存的实际用例中,可能共享同一段的两个进程将同时处于活动状态。那么,没有理由不在需要时调用shm_unlink()
。因为我在回答中做了一些假设,您能给我们提供更多关于您使用共享内存的原因的信息吗?谢谢您的回复。然而,在我的例子中,进程不知道它是“主”还是“从”。这里的全部问题是找出它是哪一个。基本上,一旦进程映射到共享内存,它就需要回答“我是第一个吗?”的问题