根据手册,如果信号量存在,则
sem_open(name, O_CREAT, mode, 1)
返回成功(信号量地址)。但调用者无法知道是否:
调用
sem_open(name, O_CREAT, mode, 0)
然后再调用单独的 sem_post()
是解决此问题的正确方法吗?
这就是调用的作用。 您告诉系统“如果信号量存在,则打开它并忽略初始值参数;如果不存在,则使用给定的初始值创建它”。 因此,只有当您不需要知道这两个调用中哪一个发生时,才应该使用此调用。
如果您确实需要知道,那么您需要编写不同的代码。 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
的评论;目前还不清楚什么时候有用。