5.2.1. Выделение и освобождение семафоров

5.2.1. Выделение и освобождение семафоров

Функции semget() и semctl() выделяют и освобождают семафоры, функционируя подобно функциям shmget() и shmctl(). Первым аргументом функции semget() является ключ, идентифицирующий группу семафоров; второй аргумент — это число семафоров в группе; третий аргумент — флаги прав доступа, как в функции shmget(). Функция semget() возвращает идентификатор группы семафоров. Если задан ключ, принадлежащий существующей группе, будет возвращен ее идентификатор. В этом случае второй аргумент (число семафоров) может равняться нулю.

Семафоры продолжают существовать даже после того, как все работавшие с ними процессы завершились. Чтобы система не исчерпала лимит семафоров, последний процесс должен явно удалить группу семафоров. Для этого нужно вызвать функцию semctl(), передав ей идентификатор группы, число семафоров в группе, флаг IPC_RMID и произвольное значение типа union semun (оно игнорируется). Значение EUID (эффективный идентификатор пользователя) процесса, вызвавшего функцию, должно совпадать с аналогичным значением процесса, создавшего группу семафоров (либо вызывающий процесс должен быть запущен пользователем root). В отличие от совместно используемых сегментов памяти, удаляемая группа семафоров немедленно освобождается.

В листинге 5.2 представлены функции, выделяющие и освобождающие двоичный семафор.

Листинг 5.2. (sem_all_deall.c) Выделение и освобождение двоичного семафора

#include <sys/ipc.h>

#include <sys/sem.h>

#include <sys/types.h>

/* Тип union semun необходимо определить самостоятельно. */

union semun {

 int val;

 struct semid_ds *buf;

 unsigned short int* array;

 struct seminfo *__buf;

};

/* Получаем идентификатор семафора и создаем семафор,

   если идентификатор оказывается уникальным. */

int binary_semaphore_allocation(key_t key, int sem_flags) {

 return semget(key, 1, sem_flags);

}

/* Освобождаем семафор, подразумевая, что пользователи

   больше не работают с ним. В случае ошибки

   возвращается -1. */

int binary_semaphore_deallocate(int semid) {

 union semun ignored_argument;

 return semctl(semid, 1, IPC_RMID, ignored_argument}

}