POSIX Семафор 'sem_post' и поведение планирования 'sem_wait' - PullRequest
0 голосов
/ 04 марта 2020

Я сталкиваюсь с небольшим раздражающим поведением при попытке синхронизировать несколько процессов с семафорами POSIX.

Я хочу убедиться, что именованный семафор, используемый несколькими процессами, не связан , когда он закончено, но только когда нет других процессов, использующих его. Согласно этой документации , когда именованный семафор не связан, любой процесс с открытым дескриптором для него может продолжать его использовать, и семафор удаляется только тогда, когда последний процесс закрывает его; но любые новые попытки sem_open семафора с тем же именем будут "ссылаться на новый семафор" .

Этот последний бит вызывает у меня проблемы, в идеале именованные Семафор будет «не связан», когда новый процесс перейдет к нему sem_open и присоединится к существующему пулу ожидающих процессов. Чтобы обойти это, я удостоверяюсь, что процессы отсоединяют семафор, только если его текущее значение равно его начальному значению. Если это так, мы знаем, что никакие другие процессы не используют его (при условии, что они симметрично sem_wait и sem_post).

Однако этот подход не работает при использовании начального значения семафора 1. Например, процесс A блокируется при вызове sem_wait, ожидающем процесса B, до sem_post именованного семафора. Когда процесс B выполняет sem_post, его программе разрешается продолжать работу, и он продолжает проверять значение семафора, видеть, что оно равно 1 (как он только что опубликовал), и отменяет его связь - все это, пока процесс A работает все еще заблокирован на sem_wait.

У меня вопрос , почему sem_post немедленно не пробуждает sem_wait -ing процесс ? Я думал, что было бы немедленное прерывание с вызовом sem_post, чтобы уведомить любые ожидающие процессы - разве это не так?

Я написал короткую программу C, чтобы продемонстрировать это:

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>

int main()
{
    sem_t* mutex = sem_open("/test", O_CREAT, 0644, 1);

    sem_wait(mutex);
    sleep(4);
    sem_post(mutex);

    // I want processes to pause here and notify other waiting processes,
    // not to continue on and unlink their semaphore!

    int sem_value;
    sem_getvalue(mutex, &sem_value);

    if (sem_value >= 1) {
        printf("Semaphore value is %d, unlinking\n", sem_value);
        sem_unlink("/test");
    }
}
...