c - 信号量和共享内存已打开/O_EXCL 标志有问题
问题描述
我目前正在开发一个具有共享内存和信号量的程序。但是我在初始化它们时遇到了问题。每当我想打开它们时(虽然 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
您的代码,如所写,只需要打开一个信号量一次,从那时起,任何信号量都不会正确,因此它们会继续存在以供下一个程序运行。
事件的顺序是:
- 在开发的某个时刻,
sem_open
无论出于何种原因失败 - 相应的
sem_close
then 失败,并且您exit(EXIT_FAILURE);
而不是执行任何剩余的调用sem_close
和所有sem_unlink
调用,因此命名信号量继续存在 - 在以后的运行中,所有
sem_open
调用O_CREAT
/O_EXCL
失败(因为它们都没有被取消链接),并且问题永远不会解决
最简单的解决方案是删除所有exit(EXIT_FAILURE);
调用(也许用调试日志替换它们);如果程序以其他方式成功运行完成,则清理失败并不那么重要;确保执行所有清理比在某些清理失败时快速失败更重要。
atexit
为每个命名信号量注册单独的处理程序也可能有意义,并且仅在 sem_open
该信号量成功之后,因此打开一个信号量不会为所有信号量注册清理函数,失败的打开也不会导致您安排清理。这样做将通过将清理限制在需要清理的情况下来减少常见故障情况下预期的故障数量。
推荐阅读
- node-red - 我如何保持 FRED 节点连接
- python - 具有多个属性的 find_all
- android - 无法移动到主要活动
- c# - C# SDK 中 AWS Lambda 的 callbackWaitsForEmptyEventLoop
- reactjs - 在 React Native 中将值传递给新屏幕
- c# - 递归获取类的字段和属性类型
- sql - impala 中的长度小于 8 位数
- python - 要求用户输入他们的用户名和密码并将其存储在文件中,如何添加包含哈希密码的字典?
- c# - 更新面板中的 C# 动态单选按钮在第一次单击时未触发?
- javascript - 如何在javascript中的字符串中添加反斜杠?