了解posix进程间信号量

Nil*_*esh 3 c++ posix semaphore

根据我的理解,信号量应该可以在相关进程中使用,而不必放在共享内存中。如果是这样,为什么以下代码会死锁?

#include <iostream>
#include <semaphore.h>
#include <sys/wait.h>

using namespace std;

static int MAX = 100;

int main(int argc, char* argv[]) {
  int retval;
  sem_t mutex;

  cout << sem_init(&mutex, 1, 0) << endl;

  pid_t pid = fork();

  if (0 == pid) {
    //     sem_wait(&mutex);
    cout << endl;
    for (int i = 0; i < MAX; i++) {
      cout << i << ",";
    }
    cout << endl;
    sem_post(&mutex);

  } else if(pid > 0) {
    sem_wait(&mutex);
    cout << endl;
    for (int i = 0; i < MAX; i++) {
      cout << i << ",";
    }
    cout << endl;
    //     sem_post(&mutex);
    wait(&retval);

  } else {
    cerr << "fork error" << endl;
    return 1;
  }

//   sem_destroy(&mutex);

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

当我在Gentoo / Ubuntu Linux上运行它时,父级挂起。显然,它没有收到孩子的职位。取消注释sem_destroy不会有任何好处。我想念什么吗?

更新1: 此代码有效

mutex = (sem_t *) mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0);
if (!mutex) {
  perror("out of memory\n");
  exit(1);
}
Run Code Online (Sandbox Code Playgroud)

谢谢,尼罗什。

cni*_*tar 5

手册页中的措词有点含糊。

如果pshared为非零,则信号量在进程之间共享,并且应位于共享内存的区域中

由于fork(2)创建的子级继承了其父级的内存映射,因此它也可以访问信号量。

是的,但是它仍然必须位于共享区域中。否则,仅使用普通的CoW复制内存即可。

您可以通过至少两种方式解决此问题:

  • 使用 sem_open("my_sem", ...)
  • 使用shm_openmmap创建共享区域

  • 而不是命名信号量,我将在分叉之前`mmap`匿名共享内存和`sem_init`对其进行过程共享。这样,您不必担心会留下必须清理的命名资源。 (2认同)