Как я могу заставить несколько вызовов sem_open работать на C?

Я испытываю большие трудности с тем, чтобы заставить семафоры работать в системе на базе Linux в C.

Процесс моего приложения таков:

  1. Приложение запускается
  2. Приложение разветвляется на дочернее/родительское
  3. Каждый процесс использует sem_open с общим именем для открытия семафора.

Если я создаю семафор перед разветвлением, он работает нормально. Однако требования не позволяют мне это сделать. Когда я пытаюсь позвонить sem_open во второй раз, я получаю сообщение об ошибке «Отказано в доступе» (через errno).

Возможно ли это сделать каким-либо образом? Или есть способ открыть семафор в одном процессе и использовать механизм общей памяти, чтобы поделиться им с дочерним процессом?


person Community    schedule 19.02.2010    source источник


Ответы (2)


Вы используете версию sem_open с 4 или 2 параметрами?

Обязательно используйте версию с 4 параметрами и используйте режим, который позволит другим процессам открывать семафор. Предполагая, что все процессы принадлежат одному и тому же пользователю, режима 0600 (S_IRUSR | S_IWUSR) будет достаточно.

Вы также можете убедиться, что umask не маскирует ни одно из необходимых разрешений.

person R Samuel Klatchko    schedule 19.02.2010
comment
Я использовал версию с четырьмя аргументами, но мои разрешения были неверными. Кажется, что O_RDWR не является флагом разрешений для использования, несмотря на то, что он появляется в каждом примере, который я смог найти. Большое спасибо. - person ; 19.02.2010

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

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/wait.h>

static void parent(void)
{
    sem_t * sem_id;
    sem_id=sem_open("mysem", O_CREAT, 0600, 0);
    if(sem_id == SEM_FAILED) {
        perror("parent sem_open");
        return;
    }
    printf("waiting for child\n");
    if(sem_wait(sem_id) < 0) {
        perror("sem_wait");
    }
}

static void child(void)
{
    sem_t * sem_id;
    sem_id=sem_open("mysem", O_CREAT, 0600, 0);
    if(sem_id == SEM_FAILED) {
        perror("child sem_open");
        return;
    }
    printf("Posting for parent\n");
    if(sem_post(sem_id) < 0) {
        perror("sem_post");
    }
}

int main(int argc, char *argv[])
{
    pid_t pid;
    pid=fork();
    if(pid < 0) {
        perror("fork");
        exit(EXIT_FAILURE);
    }

    if(!pid) {
        child();    
    } else {
        int status;
        parent();
        wait(&status);
    }
    return 0;
}
person shodanex    schedule 19.02.2010