【问题标题】:C semaphores: sem_wait throwing inexplicable errorC信号量:sem_wait抛出莫名其妙的错误
【发布时间】:2010-05-02 00:52:40
【问题描述】:

我正在处理一个我们必须使用信号量来解决的问题。我有一个数组,其中包含两个信号量gsem,并在特定条件下调用sem_wait(&(gsem[me])),它应该一直等到该特定进程被唤醒。但是,由于某种原因,它给了我错误Bad file descriptor。我查了sem_wait,Open Group 规范说这不是sem_wait 可能导致的错误。这让我的整个程序变得疯狂,我不知道为什么会失败。

编辑:违规代码,按要求。

120     sem_wait(&mutex);
121     if (inside[opp] > 0 || waiting[opp] > 0) {
122         sem_wait(&screen);
123         printf("%s %u waiting\n", names[me], t);
124         sem_post(&screen);
125         waiting[me]++;
126         sem_post(&mutex);
127         int hg = sem_wait(&(gsem[me]));
128         if (hg < 0)
129             printf("%s\n", strerror(errno));
130     } 

我应该注意,这是一项我们需要使用信号量的家庭作业。教授称其为“男女通用浴室”。男性和女性都可以使用它,但不能同时使用。 inside[opp] 是卫生间的异性人数。 waiting[opp]是等待使用的异性号码。 screen 是一个信号量,它锁定对stdout 的访问。该解决方案基于我们教科书中给出的使用传递接力棒的读者/作者问题的解决方案。

我还应该注意,我们首先必须在 Ada 中编写一个解决方案,然后将其转换为 C。我的 Ada 解决方案有效,并且我逐字翻译了它。我敢肯定这是一些小的语法细节。最后,如果有帮助的话,我正在研究 Snow Leopard。

【问题讨论】:

  • 显示代码 :-) 好吧,代码的最小版本仍然有问题。
  • 请显示您的代码,同时列出您所针对的平台/操作系统。另外,为什么不使用互斥锁?信号量没有那么快或那么健壮,具体取决于操作系统/实现
  • Sam,mutex 是互斥 semaphore 的缩写,一种特定的信号量类别,资源限制为 1。而且,即使 OP 使用其他信号量,也可能因为,我引用,“我们必须使用信号量”。 :-)
  • 是的,我知道互斥锁是什么,谢谢...但是某些类型的互斥锁比 posix 信号量更快。 Futexes,内核互斥体等。因此我的问题。
  • 添加了违规代码以供参考。还有关于问题和我的系统的详细信息。

标签: c semaphore


【解决方案1】:

请记住,在您的情况下,单一 UNIX 规范不一定是控制文档。诚然,它可能应该是,但由于您实际上没有指定平台,可能是您所处的环境决定遵循不同的规则和/或具有其他返回代码。

有几件事要检查。

1/ 你确定sem_wait 返回 -1 吗?我见过编码人员在通话后简单地检查errno,没有意识到大多数通话不会在成功时将其设置为零,而是他们只是不理会它。如果在sem_wait 调用之前将errno 设置为EBADF,则可能会出现这种情况。

2/ 你在创建信号量时是否遵循了所有规则,例如初始化它们?

3/ 你指的是一个有效的信号量吗?首先,您确定me 索引没有超出范围吗?

没有看到一些代码,这就是我必须给出的所有建议。


我用粗略的谷歌搜索sem_wait ebadf 发现的一件事是here。事实证明这是在线程环境中使用 errno 而不包括正确的标头的问题。

通过这样做,全局errno被使用,而不是正确的线程(这将提供线程特定的errno)。

这是否是你的问题,我不知道,但可能值得研究。


更紧密地跟踪该消息链,还有其他一些可能性。

4/ 您是否使用sem_init 来初始化信号量。如果是,请检查其返回值。这些消息来自 2008 年,因此可能是过时的信息,但 OSX 可能仍然不支持sem_init,更喜欢sem_open(请参阅here)。你真的应该检查 all 你的 sem_ 函数的返回码,只是为了确定(如果你对它们都使用sem_init(如果它不受支持)并且只是检查一,您可能会发现它们全部都失败了)。

5/ 在 OSX 下的线程 errno 函数链中有(曾经?)race condition,其中 __error 函数在使用 errno 之前调用了另一个库调用 pthread_self(在主线程中,或 @ 987654343@ 在其他线程中)。从技术上讲,这是不允许的,并且有一个小窗口可能会出现问题。

【讨论】:

  • 我包括errno.h,因此根据该网站,这应该不是问题。
  • 哇,你说得对,不支持sem_init。甚至没有手册页。该死的,苹果。谢谢,paxdiablo。
猜你喜欢
  • 1970-01-01
  • 2019-02-04
  • 1970-01-01
  • 1970-01-01
  • 2012-03-12
  • 1970-01-01
  • 2016-12-06
  • 2012-05-19
  • 1970-01-01
相关资源
最近更新 更多