为什么我们在初始化信号量之前取消链接?

Why We unlink semaphores before we initializes them?

我正在研究一段代码(哲学家用餐问题的解决方案),然后是程序员初始化他的信号量的部分,但是在他初始化每个信号量之前,他首先取消链接。

int sems_init(t_args *args)
{
    sem_unlink("forking");
    args->sem_forks = sem_open("forking", O_CREAT, 0644,
            args->philo_amount);
    if (args->sem_forks == SEM_FAILED)
        return (1);
    sem_unlink("writing");
    args->sem_write = sem_open("writing", O_CREAT, 0644, 1);
    if (args->sem_write == SEM_FAILED)
        return (1);
    sem_unlink("meal");
    args->sem_meal = sem_open("meal", O_CREAT, 0644, 1);
    if (args->sem_meal == SEM_FAILED)
        return (1);
    return (0);
}

我用谷歌搜索了一下,似乎 SO 社区中没有任何资源实际提到了这个。或者至少我没有找到它。
信号量初始化不会在循环中调用,也不会在此初始化之前调用(这是它们第一次在代码中初始化)。这加剧了我的困惑,我试图从代码中注释 sem_unlink() 部分,但它停止工作,即取消链接部分正在做某事,问题 为什么我们在初始化之前删除信号量即使初始化可能是第一个。

why we delete a semaphore before initialize it even though the initialization might be the first one.

因为 sem_open() 创建的命名信号量具有内核持久性。这是命名它们的部分意义所在。他们活到

  • 它们已取消链接,并且没有进程打开它们,或者
  • 系统已关闭

如果你想确保你正在创建一个新的(命名的)信号量而不是打开一个现有的信号量,那么在 sem_open() 调用之前取消链接名称很有可能。但是,如果你想确定,那么你还应该在标志中添加O_EXCL。如果具有给定名称的信号量已经存在,这将导致 sem_open() 失败,例如如果另一个进程在 sem_unlink()sem_open() 之间创建了一个信号量。

另请注意,信号量名称应以 / 开头(请参阅 sem_overview(7))。有些图书馆不强制执行,但您不应该通过省略它来无缘无故地引入可移植性问题。

另一方面,如果您只想为单个进程使用信号量,而该进程的生命周期受其宿主进程的限制,那么使用命名信号量只会让您的生活变得艰难。在这种情况下,使用匿名对象会更好,声明为 sem_t 类型的对象并通过 sem_init() 函数而不是 sem_open() 函数初始化。这将解决所有持久性和不相关的问题。