我使用sem_open
和sem_close
来创建和销毁信号量,因为sem_init
and sem_destroy
are deprecated on OS X。
第一次运行程序时,信号灯将按预期运行。在程序结束时,我调用sem_close
,它返回时没有错误。
但是,如果我再次运行该程序,则sem_open
失败,并显示errno EEXIST:
O_CREAT和O_EXCL都在oflag中指定,但是已经存在具有该名称的信号灯。sem_close
函数不仅在第一次运行期间成功返回,而且the man file建议在以下情况下在进程终止时关闭信号灯:
所有打开的命名信号量都会在处理过程中自动关闭
终止
所以我对为什么信号灯持续存在感到困惑。
MCVE
// file: pc.cc
#include <semaphore.h>
#include <pthread.h>
#include <cstdio>
#include <cstdlib>
#include <errno.h>
int main(int argc, char *argv[])
{
errno = 0;
sem_t *semaphore = sem_open("/sem3", O_CREAT | O_EXCL, 0, 0);
if (semaphore == SEM_FAILED) {
int err1 = errno;
fprintf(stderr, "sem_open() failed. errno:%d\n", err1);
if (EEXIST == err1)
fprintf(stderr, "EEXIST : Both O_CREAT and O_EXCL were specified in oflag, but a semaphore with this name already exists. \n");
}
errno = 0;
if(sem_close(semaphore) == -1){
int err2 = errno;
fprintf(stderr, "sem_close() failed. errno:%d\n", err2);
if( EINVAL == err2)
fprintf(stderr, "EINVAL : sem is not a valid semaphore.");
}
return 0;
}
第一轮和第二轮的输出
$ ./output_test
$ ./output_test
sem_open() failed. errno:17
EEXIST : Both O_CREAT and O_EXCL were specified in oflag, but a semaphore with this name already exists.
sem_close() failed. errno:9
最佳答案
我需要同时使用sem_close
和sem_unlink
。在sem_init on OS X中提到了这一点,但是我没有意识到这个意义。 This answer帮助详细说明何时使用每个功能。总结:sem_close
仅释放信号量使用的资源。封闭的信号灯会持续存在,可以重新打开。sem_unlink
标记所有进程停止使用该信号时将其销毁。
正如@JohnBollinger在评论中添加的那样,
如果仅在一次运行一遍时需要信号灯
程序,那么您应该考虑取消链接(通过sem_unlink())
创建后立即。然后,您可以继续使用它,直到
您将其关闭,但它不会阻止该程序的其他实例
使用相同的信号灯名称。而且,由于开放信号量
已关闭但未在程序退出时自动取消链接,
在发生以下情况时,可以防止信号量到处徘徊
您的程序在取消链接之前崩溃。
示例解决方案
// file: pc.cc
#include <semaphore.h>
#include <pthread.h>
#include <cstdio>
#include <cstdlib>
#include <errno.h>
int main(int argc, char *argv[])
{
errno = 0;
sem_t *semaphore = sem_open("/sem5", O_CREAT | O_EXCL, 0, 0);
sem_unlink("/sem5"); //Unlink to ensure semaphore is destroyed if program crashes
if (semaphore == SEM_FAILED) {
int err1 = errno;
fprintf(stderr, "sem_open() failed. errno:%d\n", err1);
if (EEXIST == err1)
fprintf(stderr, "EEXIST : Both O_CREAT and O_EXCL were specified in oflag, but a semaphore with this name already exists. \n");
}
//The semaphore will be closed when the program exits, but can also close it explicitly.
errno = 0;
if(sem_close(semaphore) == -1){
int err2 = errno;
fprintf(stderr, "sem_close() failed. errno:%d\n", err2);
if( EINVAL == err2)
fprintf(stderr, "EINVAL : sem is not a valid semaphore.");
}
return 0;
}
关于c - 尽管成功调用sem_close,sem_open在第二次运行程序时仍失败,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46286579/