Семафор Unix - невозможно установить начальное значение - PullRequest
0 голосов
/ 19 марта 2019

Я пытаюсь инициировать семафор UNIX, чтобы я мог использовать его для управления двумя процессами.

Я скопировал функцию sem_init из этого примера. Я удалил параметр pshared, поскольку он не использовался в функции, и исправил int * sem до int * semid, предположив, что это ошибка.

#include <iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <errno.h>

/* The semaphore key is an arbitrary long integer which serves as an
   external identifier by which the semaphore is known to any program
   that wishes to use it. */

using namespace std;

#define KEY (1492)

int sem_init(int* semid, unsigned int value) {
    /* get the semaphore */
    *semid = semget(KEY, 1, IPC_CREAT);
    if (*semid == -1) {
        printf("Unable to obtain semaphore.\n");
        return -1;
    } 

    int ret = semctl( *semid, 0, SETVAL, value);
    if (ret == -1) {
        printf("Unable to set semaphore value: %s\n", strerror(errno));
        return -1;
    }
    return ret;
}

int main(void) {
    int* semid = (int*) malloc(sizeof(int));
    sem_init(semid, 1);

    return 0;
}

Программа печатает Unable to set semaphore value: permission denied. Я также скопировал первую основную функцию из этого примера, и она печатает Cannot set semaphore value.

Одна вещь, которую я должен упомянуть, это то, что, кажется, существуют процессы, выполняющиеся в фоновом режиме с предыдущих раз, когда я запускал программу, но это не позволит мне прекратить их (он говорит, что операция не разрешена), так что, возможно, Семафор уже инициализирован, и он не позволит мне его повторно инициализировать?

Еще одна вещь. Первый пример передает IPC_CREAT | IPC_EXCL | 0666 в sem_get, но когда я делаю это, semget возвращает -1. Это работает, только если передано IPC_CREAT.

Если бы вы могли сообщить мне, что делает 0666, это было бы здорово, потому что ни один из примеров не объясняет это.

Ответы [ 2 ]

2 голосов
/ 19 марта 2019

Программа печатает Unable to set semaphore value: permission denied.

Это происходит потому, что в случае, если вызов semget(), который вы представляете, фактически создает новый набор семафоров, он создает его безправа доступа для всех.Вы, вероятно, хотите что-то вроде этого:

*semid = semget(KEY, 1, IPC_CREAT | S_IRUSR | S_IWUSR);

Это назначит режим 0600;добавьте больше разрешений по мере необходимости.Макросы S_ документируются с помощью функции open().

Одна вещь, которую я должен упомянуть, это то, что, похоже, существуют процессы, выполняющиеся в фоновом режиме по сравнению с предыдущими разами, когда я запускал программу,но он не позволит мне завершить их (в нем говорится, что операция не разрешена), поэтому, возможно, семафор уже инициализирован, и он не позволит мне повторно инициализировать его?

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

Первый пример передает IPC_CREAT | IPC_EXCL | 0666 в sem_get, но когда я это делаю, полугет возвращается -1.Это работает, только если передано только IPC_CREAT.

Это снова проблема, которую ваш семафор установил после программы.Когда вы указываете IPC_EXCL, вы явно запрашиваете сбой вызова (возвращая -1), если семафор с заданным ключом уже существует и, следовательно, не создается заново вызовом.Не должно быть вредно включать биты режима (0666) при пропуске IPC_EXCL, но они действуют только при создании нового набора семафоров.Константы S_IRUSR и S_IWUSR, на которые я ссылался выше, представляют два конкретных бита режима, и в целом я рекомендую использовать константы для числового кодирования режима.

В качестве отступления обратите внимание, что ftok()Функция - это обычное средство для получения значения ключа, с помощью которого можно идентифицировать набор семафоров.

2 голосов
/ 19 марта 2019

Проблемы с

*semid = semget(KEY, 1, IPC_CREAT | IPC_EXCL | 0666);

и

int ret = semctl( *semid, 0, SETVAL, value);

почти наверняка вызваны тем, что семафор Sys V, идентифицируемый *semid, уже существует с неправильными разрешениями, вероятно потому, что более раннее создание не учитывало разрешения 0666. Поскольку идентификатор семафора уже существует, вы не можете присоединиться к нему с установленным флагом IPC_EXCL.

Если вы работаете в Linux, команда ipcs -s покажет вам существующие семафоры Sys V. Затем вы можете использовать команду ipcrm , чтобы удалить семафор (ы) с неправильными разрешениями и начать заново.

...