POSIX 信号量的奇怪问题
Bizarre issue with POSIX semaphores
有两个信号量和两个进程。 "p1sem" 表示进程 1 等待这个信号量,进程 2 post 等待那个信号量。 "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 必须 post p1sem。 process2 也是如此,只有当 process1 posts 是 p2sem 时,它才能继续。这听起来像是某种死锁,但 posts 发生在等待之前,所以这应该不是问题。
当 process1 先启动然后我调用 process2 两次时,一切正常。
但是,如果 process2 首先启动,那么第一个会话工作正常,但是当再次调用 process2 时,两个进程都会挂起。据我了解,没有理由发生这种情况。当我调试时,挂起时信号量的值对于每个进程都是 opposite(即 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
删除那些信号量
有人看懂了吗?
如果您启动 "proc2" 然后 "proc1",它看起来像:
- "proc1" 被选中,因此它取消链接信号量,然后创建新信号量,
- 然后"proc2"被选中并取消链接新创建的信号量,
- 因此 "proc2" 的新实例创建了与之前信号量无关的新信号量。这是由
sem_open
指定的:
If a process makes repeated calls to sem_open(), with the same name
argument, the same descriptor is returned for each successful call, unless
sem_unlink() has been called on the semaphore in the interim.
"proc1" 然后 阻塞 等待任何其他进程无法访问的信号量。
有两个信号量和两个进程。 "p1sem" 表示进程 1 等待这个信号量,进程 2 post 等待那个信号量。 "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 必须 post p1sem。 process2 也是如此,只有当 process1 posts 是 p2sem 时,它才能继续。这听起来像是某种死锁,但 posts 发生在等待之前,所以这应该不是问题。
当 process1 先启动然后我调用 process2 两次时,一切正常。
但是,如果 process2 首先启动,那么第一个会话工作正常,但是当再次调用 process2 时,两个进程都会挂起。据我了解,没有理由发生这种情况。当我调试时,挂起时信号量的值对于每个进程都是 opposite(即 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
删除那些信号量有人看懂了吗?
如果您启动 "proc2" 然后 "proc1",它看起来像:
- "proc1" 被选中,因此它取消链接信号量,然后创建新信号量,
- 然后"proc2"被选中并取消链接新创建的信号量,
- 因此 "proc2" 的新实例创建了与之前信号量无关的新信号量。这是由
sem_open
指定的:
If a process makes repeated calls to sem_open(), with the same name argument, the same descriptor is returned for each successful call, unless sem_unlink() has been called on the semaphore in the interim.
"proc1" 然后 阻塞 等待任何其他进程无法访问的信号量。