理解 posix 进程间信号量

Posted

技术标签:

【中文标题】理解 posix 进程间信号量【英文标题】:Understanding the posix interprocess semaphore 【发布时间】:2011-07-28 18:05:15 【问题描述】:

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

#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 memory\n");
  exit(1);

谢谢, 尼勒什。

【问题讨论】:

您可以为您使用的语言添加标签吗?我猜是 c 或 c++,但它有助于可搜索性。 【参考方案1】:

the manual page 中的措辞有点模棱两可。

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

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

是的,但是它仍然必须在一个共享区域中。否则,内存只会被通常的CoW 复制,仅此而已。

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

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

【讨论】:

感谢您的回复!这是我没有成功的尝试... if ((mutex = sem_open("mysemaphore", O_CREAT, 0644, 0)) == SEM_FAILED) cerr 0) sem_wait(mutex); cout 确认!注释中的格式搞砸了,不知道如何解决。 我会在分叉之前mmap匿名共享内存和sem_init进程共享而不是命名信号量。这样您就不必担心留下必须清理的命名资源。 @R..:是的。但是,这将使您只能在相关进程之间使用它,或者您必须通过消息将指针传递给共享内存。您的评论在问题的上下文中是正确的,因为 OP 要求相关流程。 OTOH,如果一个旨在同步无关进程的命名资源,以后可以重用。【参考方案2】:

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

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

【讨论】:

以上是关于理解 posix 进程间信号量的主要内容,如果未能解决你的问题,请参考以下文章

IPC之Posix信号量详解

进程同步与相互排斥:POSIX有名信号量

Posix信号量

信号量

linux里的ipc是啥意思

进程间通信—信号量