2011-07-28 92 views
3

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

#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); 
} 

感谢, Nilesh制作。

+0

您可以为您正在使用的语言添加标签吗?我会猜c或C++,但它会有助于可扩展性。 – NickHeidke

回答

4

the manual page的措辞有点含糊不清。

如果的pshared为非零,则信号量进程之间共享, 和应位于共享存储器的区域。

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

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

可以在至少两种方式解决这个问题:

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

感谢您的回复!这是我没有成功的尝试......((mutex = sem_open(“mysemaphore”,O_CREAT,0644,0))== SEM_FAILED){ \t cerr <<“semaphore initilization error”<< endl; \t return 1; } pid_t pid = fork(); 如果(0 == PID){ \t/* \t如果((互斥= sem_open( “mysemaphore”,0,0644,0))== SEM_FAILED){ \t CERR << “旗语动初始化错误”< 0){ \t sem_wait(mutex); \t cout <<“here2”<< endl; \t wait(&retval); } 输出: here2 here1 – Nilesh

+0

确认!格式化在评论中混乱了,不知道如何解决这个问题。 – Nilesh

+2

而不是一个命名的信号量,我会'mmap'匿名共享内存和它处理的'sem_init' - 在分叉之前共享。这样你就不必担心离开你必须清理的命名资源。 –