我遇到了以下代码的问题:
#include "updaterankparams.hpp"
int main()
{
sem_id = semget(SEM_KEY, 1, 0);
while(true)
{
printf("want to lower: %d\n", semctl(sem_id, 0, GETVAL));
semop(sem_id, &P, 1);
printf("lowered: %d\n", semctl(sem_id, 0, GETVAL));
scanf("%*c");
puts("t");
semop(sem_id, &V, 1);
}
return 0;
}
在哪里
static sembuf P =
{
0,
-1,
0
};
static sembuf V =
{
0,
1,
0
};
我得到的输出是:
done
want to lower: 0
lowered: 0
t
want to lower: 1
lowered: 0
t
want to lower: 1
lowered: 0
当我输入字符以满足循环中的 printf 时,它会无限继续下去。 但是我希望进程在尝试降低值已经为零的信号量时停止( sleep )。但是,没有发生任何事情!我知道问这个问题可能是一件愚蠢的事情,而且解决方案也微不足道,但我想这是其中一个非常愚蠢的错误,甚至没有人在网上寻求解决方案。
只是为了澄清:没有其他进程使用信号量,并且它已在其他(现已关闭)进程中初始化,使用:
sem_id = semget(SEM_KEY, 1, 0666 | IPC_CREAT);
谢谢大家的帮助!
最佳答案
TL;DR:您必须使用 semget
创建信号量,然后使用 semop
给它一个“值”,默认值是0(整洁 :))。
据我所知,你的 P 和 V sembuf
分别是 Locking 和 Unlocking,占用 1 个资源。
编辑:您的信号量在开始时的值为 0,因为您尚未对其进行初始化。看看这个例子 given here即:
/* Semaphore does not exist - Create. */
if ((semid = semget(semkey, 1, IPC_CREAT | IPC_EXCL | S_IRUSR |
S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) != -1)
{
/* Initialize the semaphore. <- v THIS IS IMPORTANT v */
sbuf.sem_num = 0;
sbuf.sem_op = 2; /* This is the number of runs
without queuing. <- THIS IS WHERE YOU SET IT TO 1 */
sbuf.sem_flg = 0;
if (semop(semid, &sbuf, 1) == -1) {
perror("IPC error: semop"); exit(1);
}
}
我认为您在同一个信号量中混合了信号量的数量和可用资源的数量,我做到了。 semget
创建 1 个信号量,但您必须通过调用 semop
将其设置为 1 个可用资源。一个信号量可以与多个可用资源一起使用(请参见下面的训练示例)。
在您的 while
循环中,您首先使用 semop(sem_id, &P, 1);
行锁定信号量,然后您 < em>用 semop(sem_id, &V, 1);
行立即解锁。
这在您的 main
中,我猜您没有其他线程在运行,因此没有对您的资源和信号量的并发访问。您的程序将永远不必等待,因为信号量已锁定,您输入一个字符,信号量将被解锁,然后在下一个循环遍历时再次锁定。当您尝试锁定它时,您的信号量的值永远不会为 0,因为它刚刚被释放。
如果您想试用信号量并获得等待时间,请查看线程。一个很好的练习是尝试让 3 列火车只穿过一座桥,并有一个像这样的小显示,例如:
[][][][]>--------________---------
[][][][]>-------- ---------
[][][][]>-------- ---------
你的资源限制是桥梁(这里只有一个),每列火车有一个线程,做同样的事情,比如:
//Init the semaphore with 1 ressource available (the one bridge)
semop(sem_id, &V, 1);
//Threaded code :
while (position != trackSize)
{
if ((position < (bridgePosition - 1)) //Before the bridge
|| (position > bridgeEnd)) //After the bridge
{
position++;
}
else //On the bridge
{
if (semop(sem_id, &P, 1) != -1) //Lock the bridge for this train
// will wait if the bridge is already in use
{
while (position < bridgeEnd) position++; //Go through the bridge at once
}
semop(sem_id, &V, 1); //Unlock the bridge, let other trains use it
}
}
如果你有 2 个桥,你仍然会有 1 个信号量/sem_id,但你会将它设置为 2 个可用资源,这样两列火车就可以同时“锁定”同一个信号量。
我希望这能帮助您理解为什么您的程序执行时无需等待。
关于c - 信号量不会让进程休眠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23604891/