如果信号量已经存在,为什么 sem_open(O_CREAT) 的值会被忽略?

问题描述 投票:0回答:1

根据手册,如果信号量存在,则

sem_open(name, O_CREAT, mode, 1)
返回成功(信号量地址)。但调用者无法知道是否:

  • 新创建的信号量现在为 1
  • 现有信号量为 0 并且仍为 0,或者
  • 现有信号量为 1 并且仍为 1,等等

调用

sem_open(name, O_CREAT, mode, 0)
然后再调用单独的
sem_post()
是解决此问题的正确方法吗?

posix ipc semaphore glibc
1个回答
0
投票

这就是调用的作用。 您告诉系统“如果信号量存在,则打开它并忽略初始值参数;如果不存在,则使用给定的初始值创建它”。 因此,只有当您不需要知道这两个调用中哪一个发生时,才应该使用此调用。

如果您确实需要知道,那么您需要编写不同的代码。 AFAIK 没有一个调用“打开现有信号量或创建新信号量,并告诉我哪个是哪个”,但是您可以单独执行这两个操作。 使用

sem_open
而不使用
O_CREAT
将打开信号量(如果存在),如果不存在则失败。 如果信号量不存在,则使用
O_CREAT | O_EXCL
将创建信号量(具有给定的初始值),如果存在则失败。

这样你就可以做到

sem_t *s;
if ((s = sem_open("foo", 0)) != SEM_FAILED) {
    // opened existing semaphore
    // you can use sem_getvalue() to determine its current value
} else if (errno == ENOENT && (s = sem_open("foo", O_CREAT | O_EXCL, perms, 42) != SEM_FAILED) {
    // created brand-new semaphore with initial value 42
} else {
    // something wrong, handle error
}

如果另一个进程在两次调用

sem_open
之间创建了信号量,则可能会出现竞争。 在这种情况下,第二次调用将设置
errno = EEXIST
,您可以循环并重试。

我不明白你对

sem_post
的评论;目前还不清楚什么时候有用。

© www.soinside.com 2019 - 2024. All rights reserved.