问题 什么时候调用sem_unlink()?


我对Linux API sem_unlink()感到有些困惑,主要是在何时或为何调用它。我在Windows中使用了多年的信号量。在Windows中,一旦关闭了命名信号量的最后一个句柄,系统就会删除底层内核对象。但是在Linux中,开发人员需要通过调用sem_unlink()来删除内核对象。如果不这样做,内核对象将保留在/ dev / shm文件夹中。

我遇到的问题是,如果进程A调用sem_unlink()而进程B锁定了信号量,它会立即销毁信号量,当进程C出现时,进程B不再被信号量“保护”。更重要的是,手册页充其量令人困惑:

“信号量名称会立即被删除。一旦所有其他具有信号量打开的进程关闭它,信号量就会被破坏。”

如果它必须等待其他进程关闭信号量,它如何立即销毁对象?

显然,我不明白在Linux上正确使用信号量对象。谢谢你的帮助。下面是我用来测试它的一些示例代码。

int main(void)
{
    sem_t *pSemaphore = sem_open("/MyName", O_CREAT, S_IRUSR | S_IWUSR, 1);
    if(pSemaphore != SEM_FAILED)
    {
        if(sem_wait(pSemaphore) == 0)
        {
            // Perform "protected" operations here

            sem_post(pSemaphore);
        }

        sem_close(pSemaphore);
        sem_unlink("/MyName");
    }

    return 0;
}

5822
2018-03-01 18:30


起源

我认为你正在阅读手册页错了。 “信号量名称立即删除”意味着字面意思 - 删除名称,以便没有其他进程可以访问具有该名称的信号量。这并不意味着信号量被删除,只是名称。第二句描述了信号量被删除的时间 - 在当前打开信号量的每个进程都关闭之后 - twalberg
所以我想问题就变成了,你在什么时候调用sem_unlink()来删除信号量?似乎确保这种方法正常工作的唯一方法是将信号量无限期地保留在系统上。这似乎是草率的编程,但我没有看到另一种解决方案。 - user2124642
我认为这个想法是你在你决定不再希望新进程能够附加到它的任何时候删除它。系统允许已连接的进程继续运行,只有在最后一个当前活动用户消失时才收集资源。我不打算判断这是不是“草率”,但请记住,这是一个相当古老的界面/ API,所以它可能不是今天的标准“理想”,但它仍然适用于它是什么专为此而设计,因而继续有用。 - twalberg
@twalberg:“名称被删除,以便没有其他进程可以访问具有该名称的信号量。[...]信号量在当前打开的每个进程都已关闭后被删除。”但如果“没有进一步的进程可以访问信号量”,那么他们就无法关闭它。你的短语(和手册页)令人困惑,这种情况经常发生。 - Urhixidur
@Urhixidur澄清 - 没有进一步的进程意味着尚未在信号量上打开句柄的进程。那些具有开放句柄的人仍然可以关闭它,当然,否则引用计数永远不会降到0以便资源可以被释放...... - twalberg


答案:


回答您的问题:

  1. 与Windows的信号量行为相比较 describe,POSIX信号量是内核持久化的。意思是 即使没有进程具有信号量,信号量也保留它的价值 打开。 (信号量的引用计数为0)

  2. 如果进程A调用sem_unlink()而进程B具有信号量 锁定。这意味着信号量的引用计数不是0并且将会 不被破坏。

sem_close与sem_unlink的基本操作,我认为将有助于全面理解:

sem_close: close是一个信号量,这也是一个进程退出时完成的。信号量仍然存在于系统中。

sem_unlink: 只有当引用计数达到0时(即在所有打开它的进程之后,调用sem_close或退出),才会从系统中删除它。

参考文献: 书 - Unix网络编程 - 进程间通信,作者:W.Richard Stevens,第2卷,第10章


7
2018-02-22 23:16



有可能 sem_open 从那以后的另一个过程中的信号量 sem_unlink (但 sem_close 是不是被调用)这个名称被调用,还是会创建新的内核对象? - SBKarr
@SBKarr它创建了一个新的内核对象。 - Aryeh Leib Taurog


sem_unlink() 函数删除由名称和标记标识的信号量 所有进程停止使用后,信号量将被销毁(这可能意味着 如果所有打开信号量的进程已经关闭它,则立即执行。


3
2017-08-03 09:32



好,我很想知道这件事。如果在调用sem_unlink时信号量已经完全关闭,则手册页不会明确说明会发生什么。有趣的是,这意味着清理线程可以执行sem_close然后sem_unlink,或sem_unlink然后sem_close。 - Urhixidur