了解posix进程间信号量

Understanding the posix interprocess semaphore

本文关键字:信号量 进程 posix 了解      更新时间:2023-10-16

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

#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上运行这个时,父进程挂起。显然,它没有收到孩子的邮件。取消对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 memoryn");
  exit(1);
}

谢谢,里。

手册页的措辞有点模棱两可。

如果pshared非零,则信号量在进程之间共享;和应该位于共享内存的区域。

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

是的,但是它仍然必须在共享区域中。否则,内存只会用通常的CoW进行复制,就这样。

你至少可以用两种方法解决这个问题:

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

关于这个主题的一篇优秀的文章,对于未来的路人:

http://blog.superpat.com/2010/07/14/semaphores-on-linux-sem_init-vs-sem_open/