POSIX信号量在命名共享内存行为中

时间:2018-03-30 18:43:01

标签: c linux multitasking

我在共享内存中使用POSIX信号量来同步进程,并看到一些我没想到的奇怪行为。我不确定这是否是预期的行为,或者我是否做错了。

以下是背景信息:

  • 父进程是“执行”,它创建“工作”子进程,但不是一次全部。
  • 工作人员在空闲时会依靠信号量。当有工作要做时,其他一些过程(执行或其他工作人员)将发布信号量。每个worker在其等待的单独共享内存段中都有自己的信号量。
  • 在开始新的工作进程之前,父进程设置其共享内存段并初始化其中的进程共享POSIX信号量。这是通过shm_open()ftruncate()mmap()sem_init()完成的(当然,pshared标志设置为1)。
  • Parent然后执行标准fork()exec()来运行子进程。
  • 子进程然后映射相同的共享内存段,并在其“工作任务”循环中对信号量执行sem_wait()

到目前为止,所有这些都按预期工作。父/执行者可以通过调用sem_post()来释放工作进程,这样可以正常工作。

这是意外发生的地方:稍后某个时候,第二个工作人员就会启动。第二个工作人员也可能需要向第一个工作人员发出信号,因此它会映射两个内存段(它自己以及第一个工作人员的段)。

但是:当第二个工作人员在第一个工作人员的sem上调用sem_post()时,第一个工作人员不会被释放。它永远不会从其sem_wait()电话中醒来。< / p>

但是:作为调试尝试,我可以插入sleep()调用以强制在第一个工作者调用sem_wait()之前创建第二个工作程序(并映射内存)。在这种情况下,信号量按预期工作,一旦第二个工作人员呼叫sem_post(),就释放第一个工作人员。不仅是第一次通话,而且此后的每笔交易都很好。

这两项交易之间的唯一区别是mmap()来电和sem_wait()的顺序:

如果是A,则sem_wait()首先发生,然后是另一个调用mmap()sem_post()的流程。

在案例B中,mmap()首先发生(这样两个映射到内存的进程都映射到它),然后是sem_wait() / sem_post()。这很有效。

所以问题是:这是预期的行为吗? 如果是这样,为什么在第一个进程之后第二个进程映射到并发布一个信号量就不能用了?

我的测试系统是x86-64 / Ubuntu 16.04 / Linux 4.13.0。

谢谢!

0 个答案:

没有答案