Можно ли создать глобальный семафор для всех процессов?

У меня проблема с семафором в моем коде.

Это структура, которую я построил:

struct PipeShm
{
        // doesn't matter 
        sem_t *mutex;
        int init;
        // more fields
};

Здесь я инициализирую структуру:

struct PipeShm myPipe ;
myPipe.mutex = NULL;
myPipe.init = 0;

И я использую метод инициализации:

int initMethod()
{
    if (!myPipe.init)
    {
        myPipe.mutex = mmap (NULL, sizeof *myPipe.mutex, PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANONYMOUS, -1, 0);
        if (!sem_init (myPipe.mutex, 1, 0))
        {
            myPipe.init = TRUE;
        }
        else
            perror ("initMethod");
    }
    return 1;   
}

Это простой main , который использует вышеописанное:

int main()

{
    int spd, pid, rb;
    char buff[4096];


    shm_pipe_init();
    fork();

        // more code goes here 

        return 0;
}

В строке fork(); (пожалуйста, поправьте меня, если я ошибаюсь) процессы 2 будут иметь два разных семафора, верно?

Если это так, я хочу сделать глобальный семафор. Это возможно?

Из-за проблем с синхронизацией в моем коде подозреваю, что основная причина - двойной семафор для каждого создаваемого процесса.


person JAN    schedule 30.07.2012    source источник
comment
@tbert: я не могу это использовать (я имею в виду файлы)   -  person JAN    schedule 30.07.2012
comment
тогда вы можете заглянуть в свои справочные страницы, потому что man sem_init привел меня к sem_open, в котором говорится: Функция sem_open() устанавливает соединение между именованным семафором и процессом, который выглядит точно так же, как то, что вы пытаетесь сделать здесь.   -  person tbert    schedule 30.07.2012
comment
Ваш код для создания и инициализации семафора выглядит так, как будто вы пытаетесь поступить правильно. Вы столкнулись с конкретной проблемой при использовании семафора?   -  person jxh    schedule 30.07.2012
comment
@ user315052: Да, мои процессы постоянно сталкиваются друг с другом, хотя я использую семафоры и блокировки. Я действительно понятия не имею, что вызывает это, я пытался отладить это бесчисленное количество раз, но нада. Мой единственный вывод состоит в том, что семафор не используется всеми процессами, и это делает весь ад тормозным... Например: вместо того, чтобы получать 2 outputs, когда я fork, я получаю один раз 2 outputs, а другой раз 1 output   -  person JAN    schedule 30.07.2012
comment
Я уже говорил вам по вашему другому вопросу на ту же тему, что вы должны иметь поле init также внутри общего сегмента, это не может работать так. Вы должны иметь всю свою общую структуру управления в сегменте. Вы видели мой ответ, там? stackoverflow.com/questions/11708049/   -  person Jens Gustedt    schedule 30.07.2012
comment
@JensGustedt: в этом нет необходимости, если семафор инициализируется до fork. Но если процедура инициализации вызывается после вызова fork, вы правы в том, что флаг инициализации также должен находиться в общей памяти.   -  person jxh    schedule 31.07.2012
comment
@JensGustedt: Йенс, я сделал именно то, что ты сказал, и все равно получаю тот же результат. Должен ли я загрузить новый код, чтобы вы могли взглянуть и, возможно, сказать мне, если вы видите что-то не так? очень признателен !   -  person JAN    schedule 31.07.2012
comment
@ron, сначала создайте минимальный пример, который точно воспроизводит вашу проблему. Он должен состоять всего из нескольких строк, быть полным и надежно воспроизводить проблему (на вашей платформе). Обычно, создавая такой и пример, вы находите ошибку :) Если у вас есть такой пример, а ваш профессор не может или не хочет вам помочь, задайте новый вопрос.   -  person Jens Gustedt    schedule 31.07.2012


Ответы (1)


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

void do_child () {
    fprintf(stderr, "[%u] child: waiting...\n", (unsigned)time(0));
    sem_wait(myPipe.mutex);
    fprintf(stderr, "[%u] child: sleeping 1...\n", (unsigned)time(0));
    sleep(1);
    fprintf(stderr, "[%u] child: posting...\n", (unsigned)time(0));
    sem_post(myPipe.mutex);
    fprintf(stderr, "[%u] child: done...\n", (unsigned)time(0));
}

void do_parent (pid_t p) {
    fprintf(stderr, "[%u] parent: sleeping 5...\n", (unsigned)time(0));
    sleep(5);
    fprintf(stderr, "[%u] parent: posting...\n", (unsigned)time(0));
    sem_post(myPipe.mutex);
    fprintf(stderr, "[%u] parent: waiting...\n", (unsigned)time(0));
    sem_wait(myPipe.mutex);
    fprintf(stderr, "[%u] parent: waitpid...\n", (unsigned)time(0));
    waitpid(p, 0, 0);
    fprintf(stderr, "[%u] parent: done...\n", (unsigned)time(0));
}

int main () {
    pid_t p;
    myPipe.mutex = NULL;
    myPipe.init = 0;
    initMethod();
    switch ((p = fork())) {
    case 0:  do_child(); break;
    case -1: perror("fork"); break;
    default: do_parent(p); break;
    }
    return 0;
}

Я думаю, вы уже знаете, но на всякий случай семафор на самом деле не мьютекс. Вы можете думать о мьютексе как о семафоре, который инициализируется значением поста 1. Но семафор не предотвращает несколько одновременных сообщений. Если у вас есть ложные сообщения в семафоре, это позволит более чем одному потоку попасть в критическую секцию.

person jxh    schedule 30.07.2012