Правильное удаление семафора SYS V, используемого несколькими процессами

У меня есть проект, в котором я должен использовать семафоры SYS V. У меня есть несколько процессов, которые разделяют семафор (используя тот же ключ) и инициализируют его с помощью этого кода:

bool semaphore_init(semaphore_id_t* sem, int sem_value, key_t key)
{
    /* Try to get a semaphore, to check if you will be an owner */
    *sem = semget(key, 1, IPC_CREAT | IPC_EXCL | 0666);
    if (*sem == -1)
    {
        if (errno == EEXIST)
        {
            /* We are not owners, get semaphore without exclusive flag */
            *sem = semget(key, 1, IPC_CREAT | 0666);
            if (*sem == -1) return false;
        }
        else return false;
    }
    else
    {
        /* We are owners, initialize semaphore */
        int return_value = semctl(*sem , 0, SETVAL, sem_value);
        if (return_value == -1) return false;
    }

    return true;
}

Моя проблема: я хочу удалить этот семафор, когда все процессы, использующие его, будут прерваны. С помощью:

semctl(*sem, 0, IPC_RMID)

это не вариант. Он мгновенно удаляет семафор, а другие процессы получают неопределенное поведение. Я просто не могу найти правильный способ сделать это с SYS V API.

1 ответ

Вы можете использовать подсчет ссылок. Просто сделайте так, чтобы каждый процесс увеличивал счетчик ссылок после инициализации семафора и уменьшал его, когда процесс завершался. Последний, уменьшивший его до 0, также удалит его, или главный процесс очистит его, когда узнает, что все остальные процессы завершены.

Возможно, вам также понадобится другой механизм блокировки для синхронизации доступа к счетчику ссылок, который вы, вероятно, создадите / удалите в главном процессе, который порождает и ожидает другие процессы.

Кроме того, следите за висячими ссылками, если ваши процессы могут ненормально завершиться.

Другие вопросы по тегам