2017-08-29 91 views
1

有两个信号量和两个进程。 “p1sem”表示process1在此信号量上等待并且process2发布该信号量。 “p2sem”恰恰相反。这两个进程初始化值为0(如果它们还没有被创建)POSIX信号量的奇怪问题

因此,process1运行两个会话打开和删除这两个信号量。 process2只运行一个会话,但应该再次调用以耗尽process1的下一个会话。这是代码的样子:

进程2:

#include <semaphore.h> 
#include <fcntl.h> 

int main(){ 
    sem_t *waitSem = sem_open("p2sem", O_CREAT, 0666, 0); 
    sem_t *postSem = sem_open("p1sem", O_CREAT, 0666, 0); 

    // tic for a cycle 
    sem_post(postSem); 
    sem_wait(waitSem); 

    // close and exit 
    sem_close(waitSem); 
    sem_close(postSem); 
    sem_unlink("p2sem"); 
    sem_unlink("p1sem"); 
} 

过程1:

#include <semaphore.h> 
#include <fcntl.h> 

int main() { 
    for(int i = 0; i < 2; i++) { 

     // create sems 
     sem_t *waitSem = sem_open("p1sem", O_CREAT, 0666, 0); 
     sem_t *postSem = sem_open("p2sem", O_CREAT, 0666, 0); 

     // tic for a cycle 
     sem_post(postSem); 
     sem_wait(waitSem); 

     // close and exit 
     sem_close(waitSem); 
     sem_close(postSem); 
     sem_unlink("p2sem"); 
     sem_unlink("p1sem"); 
    } 
} 

为了让过程1继续,过程2有张贴p1sem。 process2也一样,只有process1发布它是p2sem才能继续。这可能听起来像是某种僵局,但这些帖子是在等待之前发生的,所以这应该不成问题。

当process1第一次启动,然后我调用process2两次,事情工作正常。

但是,如果process2首先启动,那么第一个会话正常工作,但是当再次调用process2时,两个进程都会挂起。据我了解,这没有理由发生。当我调试时,悬挂时刻信号量的值是,对于每个进程,对于(即p1sem在process1的值为0,但在process2的值为1,对于p2sem是相同的。)我附加了gdb的图片在信号值的__align =中,我认为大的正数表示负-1,它是 - 等待该信号量的进程数,至少根据http://man7.org/linux/man-pages/man3/sem_getvalue.3.html)。您还可以通过gdb调用sem_post和sem_wait来玩游戏但是您会看到无论您调用哪个进程,它都不会影响另一个进程的信号量值。

/dev/shm包含sem.p1sem和sem.p2sem。如果人们想测试这个,然后重新启动过程中,你必须删除这些信号与rm sem.p1sem sem.p2sem

有没有人明白这一点?

enter image description here

回答

1

如果启动 “PROC2”,然后 “PROC1”,它看起来像:

  • “PROC1” 当选,因此解除链接信号灯,然后创建新的,
  • 然后“proc2”被选中并且断开新创建的信号量
  • 因此“proc2”的新实例创建与先前无关的新信号量。这是由sem_open规定:

如果一个过程使重复调用sem_open(),具有相同的名称 的说法,同样的描述符返回每次成功通话,除非 sem_unlink()被调用在信号量的过渡期间。

“PROC1”随后被阻塞等待信号量即没有更多的可访问的任何其他过程。

+0

感谢您的回答! 我还是不明白第三步。事情是,这些被命名为信号量,所以除非我失去了一些东西,那么它们不应该与以前的东西无关,因为它们具有相同的名称(p1sem,p2sem) 另外,在第一次,当proc1取消链接时,它不会从操作系统中删除信号量,因为它们仍可从proc2访问。所以当它继续创建“新的”时,它们并不是真正的新的,sem_open应该返回那里已经存在的信号量。 (O_CREAT标志意味着它应该创建信号量,如果它不存在) – burnedWood

+1

唉不,这就像文件一样,如果你删除它然后重新创建它就是不同的文件。来自'sem_open'手册的引用*如果进程对sem_open()进行重复调用,并且名称相同,则每次成功调用都会返回相同的描述符,除非在信号量上调用了sem_unlink()临时。* –

+0

谢谢Jean-Baptiste,我现在明白了! – burnedWood