Когда процесс открывает именованный семафор, между ними устанавливается связь на уровне записи, которая создается системой. Функция sem_close() удаляет эту связь (то есть закрывает семафор), освобождает все выделенные на нее ресурсы и уменьшает счетчик ссылок на семафор.

#include

int sem_close(sem_t *sem);

Возвращает 0 при успешном завершении или -1 при ошибке

Когда процесс завершается или выполняет вызов exec(), открытые им именованные семафоры автоматически закрываются. Закрытие семафора не приводит к его удалению. Для этого нужно использовать функцию sem_unlink().

49.2.3. Удаление именованного семафора

Функция sem_unlink() удаляет семафор с именем name и делает его кандидатом на удаление, которое происходит, когда все процессы перестают его использовать (удаление может случиться сразу же, если все другие процессы уже закрыли данный семафор).

#include

int sem_unlink(const char *name);

Возвращает 0 при успешном завершении или -1 при ошибке

Применение функции sem_unlink() продемонстрировано в листинге 49.2.

Листинг 49.2. Использование функции sem_unlink() для удаления именованного POSIX-семафора

psem/psem_unlink.c

#include

#include "tlpi_hdr.h"

int

main(int argc, char *argv[])

{

if (argc!= 2 || strcmp(argv[1], "-help") == 0)

usageErr("%s sem-name\n", argv[0]);

if (sem_unlink(argv[1]) == -1)

errExit("sem_unlink");

exit(EXIT_SUCCESS);

}

psem/psem_unlink.c

49.3. Операции с семафорами

POSIX-семафор — целое число, которое не может быть меньше нуля. Операции с такими объектами имеют следующие особенности:

• функции sem_post() и sem_wait(), изменяющие значения семафоров, делают это для каждого семафора отдельно и не поддерживают групповых операций;

• функции sem_post() и sem_wait() инкрементируют и декрементируют значения семафоров ровно на 1;

• POSIX-семафоры не поддерживают операции ожидания нулевого значения.

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

49.3.1. Декрементация семафора

Функция sem_wait() декрементирует (уменьшает на 1) значение семафора, на который указывает аргумент sem.

#include

int sem_wait(sem_t *sem);

Возвращает 0 при успешном завершении или -1 при ошибке

Если семафор имеет значение больше нуля, то функция sem_wait() сразу же завершится. Когда семафор равен 0, функция sem_wait() заблокируется до тех пор, пока его значение не станет положительным; когда это случится, он будет декрементирован, а функция sem_wait() завершит свою работу.

При прерывании вызова sem_wait() с помощью обработчика сигнала он завершится ошибкой EINTR; использование флага SA_RESTART в вызове sigaction() (когда этот обработчик создавался) не будет играть никакой роли (в некоторых реализациях UNIX флаг SA_RESTART приводит к автоматическому перезапуску данного вызова).

Программа, показанная в листинге 49.3, предоставляет интерфейс командной строки к функции sem_wait(). Ее применение будет продемонстрировано чуть позже.

Листинг 49.3. Использование функции sem_wait() для декрементации POSIX-семафора

psem/psem_wait.c

#include

#include "tlpi_hdr.h"

int

main(int argc, char *argv[])

{

sem_t *sem;

if (argc < 2 || strcmp(argv[1], "-help") == 0)

usageErr("%s sem-name\n", argv[0]);

sem = sem_open(argv[1], 0);

if (sem == SEM_FAILED)

errExit("sem_open");

if (sem_wait(sem) == -1)

errExit("sem_wait");

printf("%ld sem_wait() succeeded\n", (long) getpid());

exit(EXIT_SUCCESS);

}

psem/psem_wait.c

Функция sem_trywait() является неблокирующей версией sem_wait().

#include

int sem_trywait(sem_t *sem);

Возвращает 0 при успешном завершении или -1 при ошибке

Если декрементация не может быть выполнена немедленно, то вызов sem_trywait() завершается ошибкой EAGAIN.

Функция sem_timedwait() представляет собой еще одну разновидность sem_wait(). Она позволяет вызывающему процессу ограничить время блокирования вызова.

#define _XOPEN_SOURCE 600

#include

int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);

Возвращает 0 при успешном завершении или -1 при ошибке

Если вызов sem_timedwait() не успевает выполнить декрементацию семафора за отведенное ему время, то завершается ошибкой ETIMEDOUT.

Перейти на страницу:

Похожие книги