c - 信号量不会让进程休眠

标签 c linux ipc semaphore

我遇到了以下代码的问题:

#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/

相关文章:

linux - 无法写入我所属组的文件夹

linux - 配置 gnuplot 以处理像 excel 这样的时间序列

Android:AIDL 的安全 IPC 替代品?

c - 无法写入 2 个进程的管道 IPC

c - 你认为这种糟糕的编码风格吗?

c - 为什么在头文件中使用 typedef 而不是只在 .c 中做所有事情

c - 如何在 C 中将字符串 "this is a string of words"作为 argv[1] 打印出来?

c - 管道 : write to front of pipe

linux - Bash - 运行 grep 返回的命令

python - 从Python中其他进程中运行的函数调用类方法