【问题标题】:Bizarre issue with POSIX semaphoresPOSIX 信号量的奇怪问题
【发布时间】:2018-02-06 20:01:40
【问题描述】:

有两个信号量和两个进程。 “p1sem”表示 process1 等待此信号量,而 process2 发布该信号量。 “p2sem”则相反。两个进程都将值初始化为 0(如果尚未创建)

因此,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");
    }
}

为了让 process1 继续,process2 必须发布 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 删除这些信号量

有人明白吗?

【问题讨论】:

    标签: c posix semaphore


    【解决方案1】:

    如果你启动“proc2”然后“proc1”,它看起来像:

    • “proc1”被选中,因此它取消链接信号量,然后创建新信号量,
    • 然后选择“proc2”并取消链接新创建的信号量,
    • 因此,“proc2”的新实例会创建与先前信号量无关的新信号量。这是由sem_open指定的:

    如果一个进程重复调用 sem_open(),同名 参数,每次成功调用都返回相同的描述符,除非 在此期间,已在信号量上调用了 sem_unlink()。

    “proc1”然后阻塞等待任何其他进程无法访问的信号量。

    【讨论】:

    • 感谢您的回答!我还是不明白第三步。问题是这些被命名为信号量,所以除非我遗漏了什么,否则它们不应该与以前的信号量无关,因为它们具有相同的名称(p1sem,p2sem)此外,首先,当 proc1 取消链接时,它不会'不要从操作系统中删除信号量,因为它们仍然可以从 proc2 访问。因此,当它继续创建“新的”时,它们并不是真正的新的,sem_open 应该返回那里已经存在的信号量。 (O_CREAT 标志意味着它应该创建信号量,如果它不存在)
    • 唉,不,这就像文件,如果你删除它然后重新创建它是不同的文件。引用自 sem_open 的手册 如果一个进程使用相同的名称参数重复调用 sem_open(),则每次成功调用都会返回相同的描述符,除非已在临时。
    • 谢谢让-巴蒂斯特,我现在明白了!
    猜你喜欢
    • 2013-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多