我对 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;
}
回复您的问题:
与 Windows 的信号量行为相比,您 描述一下,POSIX 信号量是内核持久的。这意味着 即使没有进程拥有信号量,信号量仍保留其值 打开。 (信号量的引用计数将为 0)
如果进程A调用sem_unlink(),而进程B拥有信号量 锁定。这意味着信号量的引用计数不为 0,并且将 不被破坏。
sem_close 与 sem_unlink 的基本操作,我认为将有助于整体理解:
sem_close:close是一个信号量,当进程退出时也会完成。信号量仍然保留在系统中。
sem_unlink:仅当引用计数达到 0 时(即在所有打开它的进程、调用 sem_close 或退出之后), 才会从系统中删除。
参考资料: 书籍 - Unix 网络编程 - 进程间通信,作者:W.Richard Stevens,第 2 卷,第 10 章
sem_unlink()
函数删除由名称和标记标识的信号量
一旦所有进程停止使用信号量就会被销毁(这可能意味着
立即,如果所有打开信号量的进程都已关闭它)。
我认为最简单的理解方法是将行为与文件和文件句柄进行比较。
open()
创建/打开文件时,该文件会在文件系统中(通常在磁盘中)创建,并且进程会获得一个 文件句柄,即一个数字。close()
关闭文件句柄时,进程将无法再访问该文件,但该文件仍然存在于磁盘上。unlink()
删除文件时,如果您使用 ls
bash 命令,您将不再在其包含的目录中看到该文件名;然而,仍然可以通过文件句柄访问该文件,并且 inode 仍然存在。这3种情况分别对应
sem_open
、sem_close
和sem_unlink
。 sem_t*
对应于文件句柄。
事实上,命名信号量是作为文件实现的。
类似地,如果您取消链接信号量而不关闭它,然后创建一个具有相同名称的新信号量,则行为就像您对文件执行相同的操作一样 - 即您将获得两个“具有相同名称”的不同信号量:
#include <fcntl.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <semaphore.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
int main(){
sem_t *a1 = sem_open("a", O_CREAT | O_EXCL, 0644, 1);
assert(a1 != SEM_FAILED);
sem_unlink("a");
sem_t *a2 = sem_open("a", O_CREAT | O_EXCL, 0644, 2);
assert(a2 != SEM_FAILED);
sem_unlink("a");
int a1value, a2value;
assert(sem_getvalue(a1, &a1value) == 0);
assert(sem_getvalue(a2, &a2value) == 0);
assert(a1value == 1);
assert(a2value == 2);
sem_close(a1);
sem_close(a2);
}
这是什么意思?那个