理解posix进程间信号量

3
根据我的理解,一个信号量应该可以在相关进程中使用,而不需要将它放置在共享内存中。如果是这样的话,为什么以下代码会出现死锁呢?
#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;
}

当我在 Gentoo/Ubuntu Linux 上运行此代码时,父进程卡住了。显然,它没有接收到子进程的post。取消 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);
}

感谢您,Nilesh。

你能为使用的编程语言添加一个标签吗?我猜测是C或C++,但这会增加搜索的效率。 - Nick Heidke
2个回答

5
手册页面中的措辞有些模棱两可。

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

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

是的,但它仍然必须位于共享区域内。否则,内存只是使用通常的CoW进行复制,就这样了。
您可以通过以下至少两种方式解决此问题:
  • 使用sem_open("my_sem", ...)
  • 使用shm_openmmap创建共享区域

谢谢您的回复!这是我尝试过但没有成功的代码... if ((mutex = sem_open("mysemaphore", O_CREAT, 0644, 0)) == SEM_FAILED) { cerr << "semaphore initilization error" << endl; return 1; } pid_t pid = fork(); if (0 == pid) { /* if ((mutex = sem_open("mysemaphore", 0, 0644, 0)) == SEM_FAILED) { cerr << "semaphore initilization error" << endl; return 1; } */ cout << "here1" << endl; sem_post(mutex); } else if(pid > 0) { sem_wait(mutex); cout << "here2" << endl; wait(&retval); } 输出结果: here2 here1 - Nilesh
糟糕!注释中的格式混乱了,不知道该如何修复。 - Nilesh
3
与其使用命名信号量,我建议使用匿名共享内存进行mmap,并在fork之前使用sem_init进行进程间共享。这样您就不必担心留下需要清理的命名资源。 - R.. GitHub STOP HELPING ICE
@R..:是的。然而,这只能让你在相关进程之间使用它,或者你必须通过消息传递指向共享内存的指针。在问题的上下文中,您的评论是正确的,因为OP要求相关进程。另一方面,如果一个人旨在同步不相关的进程,那么命名资源可以在以后被重复使用。 - user1284631

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接