我使用sem_opensem_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_closesem_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/

10-15 01:31
查看更多