【问题标题】:using POSIX counting semaphore as a binary semaphore使用 POSIX 计数信号量作为二进制信号量
【发布时间】:2015-11-16 17:56:15
【问题描述】:

我正在尝试将POSIX counting semaphore 用作binary semaphore

为此,我编写了以下代码

sem = sem_open(argv[optind], flags, perms, 1); // Initialising semaphore to 1

    while(sem_getvalue(sem) > 0)
    {
    continue;

    }
    sem_post(sem);

还有其他方法可以将计数信号量用作二进制信号量吗?在这里,如果在 while lopp 被评估为 false 之后立即发生 comtext 切换,但尚未调用 sem_post,那么在这种情况下不会导致竞争条件吗?对于我想要实现的目标,还有其他更好的选择吗?

我有多个进程与信号量同步。我知道这段代码不能保证一个场景,在 sem_getvalue 期间,即使sem 值变为零,甚至在调用特定进程中的 sem_post 之前,anotehr 进程也可能调用 sem_post,导致值为 2。如何这种情况是可以解决的。

互斥锁无法解决我的问题,因为在我的问题中,有些进程仅用于信号,即sem_post 操作,与互斥锁不同,所有进程都将不断等待和发出信号

【问题讨论】:

标签: c linux posix ipc semaphore


【解决方案1】:

您发布的代码存在一些问题。

while(sem_getvalue(sem) > 0)

这被称为忙等待,这意味着进程在信号量上旋转并且不会将 CPU 让给调度程序。通常,只有在等待应该小于上下文切换时间(例如低延迟)的情况下才会进行忙等待。

下一个问题是你的语义是倒置的。当信号量大于 0 时,您递减并继续。此外,您的调用不是原子的,这会引入许多竞争条件。

实际上,您需要互斥体语义,因为只有两种状态(0/锁定和 1/解锁)。为此,您可以保证sem_post 永远不会继续sem_wait,或者您可以使用文件锁。

const char* lock_file = ".lock";

const int fd_lock = open(lock_file, O_CREAT);

flock(fd_lock, LOCK_EX);

// do stuff

flock(fd_lock, LOCK_UN);

// do more stuff

close(fd_lock);    
unlink(lock_file);

POSIX 变体将涉及fcntl 而不是flock

【讨论】:

  • 不会使用文件锁减慢进程,因为文件操作会造成不必要的延迟。这里也可以有多个进程,可以进行信号量信号操作。事实上有一些进程,只会做信号操作。所以这不是典型的互斥操作。
  • 感谢您的投入,但我正在寻找基于信号量的解决方案,而不是文件锁定操作。
  • 不,互斥锁、信号量和文件锁都在内核中实现,因为进程需要阻塞它们。锁定文件通常是空的,锁定/解锁并不意味着任何 I/O。您描述的语义与互斥锁有何不同?
  • 您假设所有进程都会执行 lcok,然后会执行解锁。但就我而言,有一些进程,只会解锁
  • 我不确定您要完成什么,通常信号量/互斥量代表共享资源。如果不知道某事是否已完成,它如何发布/解锁?你在做什么听起来更像是一个 POSIX 队列。
猜你喜欢
  • 2011-07-29
  • 2020-12-23
  • 2017-10-03
  • 1970-01-01
  • 1970-01-01
  • 2015-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多