信号量和共享内存已经打开/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 信号量,所以他们在下一个节目中继续存在 运行.
事件的顺序是:
- 在开发的某个阶段,
sem_open
出于某种原因失败了
- 相应的
sem_close
然后失败,您 exit(EXIT_FAILURE);
而不是执行任何剩余的 sem_close
调用和 all sem_unlink
调用,所以命名的信号量继续存在
- 在未来的 运行 中,所有
sem_open
调用 O_CREAT
/O_EXCL
失败(因为其中 none 未链接),问题永远不会固定
最简单的解决方案是删除所有 exit(EXIT_FAILURE);
调用(也许用调试日志替换它们);如果程序 运行 成功完成,则清理失败并不那么重要;确保执行所有清理比在某些清理失败时快速失败更重要。
为每个命名信号量注册单独的 atexit
处理程序也可能有意义,并且只有 after sem_open
该信号量成功,因此打开一个信号量不会为所有这些注册清理函数,打开失败也不会导致您安排清理。通过将清理限制在需要清理的情况下,这样做可以减少常见故障情况下预期的失败次数。
我目前正在开发一个具有共享内存和信号量的程序。但是我在初始化它们时遇到了问题。每当我想打开它们时(虽然 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 信号量,所以他们在下一个节目中继续存在 运行.
事件的顺序是:
- 在开发的某个阶段,
sem_open
出于某种原因失败了 - 相应的
sem_close
然后失败,您exit(EXIT_FAILURE);
而不是执行任何剩余的sem_close
调用和 allsem_unlink
调用,所以命名的信号量继续存在 - 在未来的 运行 中,所有
sem_open
调用O_CREAT
/O_EXCL
失败(因为其中 none 未链接),问题永远不会固定
最简单的解决方案是删除所有 exit(EXIT_FAILURE);
调用(也许用调试日志替换它们);如果程序 运行 成功完成,则清理失败并不那么重要;确保执行所有清理比在某些清理失败时快速失败更重要。
为每个命名信号量注册单独的 atexit
处理程序也可能有意义,并且只有 after sem_open
该信号量成功,因此打开一个信号量不会为所有这些注册清理函数,打开失败也不会导致您安排清理。通过将清理限制在需要清理的情况下,这样做可以减少常见故障情况下预期的失败次数。