信号量和共享内存已经打开/O_EXCL 标志有问题

Semaphores and shared memory already opened / Problem with O_EXCL flag

我目前正在开发一个具有共享内存和信号量的程序。但是我在初始化它们时遇到了问题。每当我想打开它们时(虽然 O_EXCL 标志处于活动状态,但我不断收到错误。这应该意味着它们在开始时已经打开,但我不知道如何或为什么。

static sem_t *s1 = NULL;

void initSEM(void)
{
    atexit(closeSEM);
    s1 = sem_open(SEM_1, O_CREAT | O_EXCL, 0600, 1);
    if (s1 == SEM_FAILED)
    {
        printf("%s", "ERROR: Semaphore 1 could not be opened.");
        exit(EXIT_FAILURE);
    }
}

void closeSEM(void)
{
    if (sem_close(s1) == -1)
    {
        exit(EXIT_FAILURE);
    }
    if (sem_close(s2) == -1)
    {
        exit(EXIT_FAILURE);
    }
    if (sem_close(s3) == -1)
    {
        exit(EXIT_FAILURE);
    }
    if (sem_unlink(SEM_1) == -1)
    {
        exit(EXIT_FAILURE);
    }
    if (sem_unlink(SEM_2) == -1)
    {
        exit(EXIT_FAILURE);
    }
    if (sem_unlink(SEM_2) == -1)
    {
        exit(EXIT_FAILURE);
    }
}

在我的主要功能中,我只是调用它。共享内存也一样。我不知道为什么会这样。

你的代码,正如所写的那样,只需要打开一个信号量失败一次,从那时起,将永远不会正确地 sem_unlink any 信号量,所以他们在下一个节目中继续存在 运行.

事件的顺序是:

  1. 在开发的某个阶段,sem_open 出于某种原因失败了
  2. 相应的 sem_close 然后失败,您 exit(EXIT_FAILURE); 而不是执行任何剩余的 sem_close 调用和 all sem_unlink调用,所以命名的信号量继续存在
  3. 在未来的 运行 中,所有 sem_open 调用 O_CREAT/O_EXCL 失败(因为其中 none 未链接),问题永远不会固定

最简单的解决方案是删除所有 exit(EXIT_FAILURE); 调用(也许用调试日志替换它们);如果程序 运行 成功完成,则清理失败并不那么重要;确保执行所有清理比在某些清理失败时快速失败更重要。

为每个命名信号量注册单独的 atexit 处理程序也可能有意义,并且只有 after sem_open 该信号量成功,因此打开一个信号量不会为所有这些注册清理函数,打开失败也不会导致您安排清理。通过将清理限制在需要清理的情况下,这样做可以减少常见故障情况下预期的失败次数。