15

我对 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;
}
4

2 回答 2

13

回答您的问题:

  1. 与您描述的窗口的信号量行为相比,POSIX 信号量是内核持久的。这意味着即使没有进程打开信号量,信号量也会保留其价值。(信号量的引用计数为 0)

  2. 如果进程 A 调用 sem_unlink() 而进程 B 已锁定信号量。这意味着信号量的引用计数不为 0,不会被破坏。

sem_close vs sem_unlink的基本操作,我觉得会有助于整体理解:

sem_close:关闭是一个信号量,当进程退出时也会这样做。信号量仍保留在系统中。

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

参考资料: W.Richard Stevens 所著的书 - Unix 网络编程 - 进程间通信,第 2 卷,第 10 章

于 2014-02-22T23:16:40.920 回答
4

sem_unlink()函数删除由名称标识的信号量,并在所有进程停止使用它时将其标记为销毁(这可能意味着立即,如果所有打开信号量的进程都已经关闭它)。

于 2016-08-03T09:32:39.197 回答