Unix - статьи



         

Семафоры


Семафоры широко используются как средство синхронизации потоков и процессов. В Unix-системах реализованы три типа семафоров – семафоры System V, семафоры POSIX и семафоры в разделяемой памяти. Поскольку статья посвящена System V IPC, мы рассмотрим семафоры System V. Подробное описание всех трех типов семафоров можно найти в [].

Состояние семафора определяется значением некоторой внутренней переменной и переданным ему параметром. В зависимости от этих значений семафор либо приостанавливает выполнение обратившегося к нему потока (до тех пор, пока другой поток не переведет семафор в другое состояние), либо изменяет значение внутренней переменной, разрешив потоку дальнейшее выполнение. Следующая функция иллюстрирует логику работы семафора в зависимости от значения переменной состояния (semvalue) и управляющей переменной sem_op.

void semaphore (int sem_op) { static int semvalue; // Внутренняя переменная if (sem_op != 0) { if (sem_op < 0) while (semvalue < ABS(sem_op)); semvalue += sem_op; } else while (semvalue != 0); }

Отрицательное значение sem_op соответствует операции проверки доступности ресурса и вызывает приостановку потока, если доступ к ресурсу заблокирован. Положительное значение сигнализирует о высвобождении ресурса. Приведенная выше функция semaphore() описывает поведение многозначного семафора (general semaphore). Именно такие семафоры используются в System V IPC. Перепишем клиент и сервер из предыдущего примера, заменив спин- блокировки семафорами (на диске вы найдете исходный текст сервера в файле semserv.c, а исходный текст клиента – в файле semcli.c. Все, что касается семафоров, определено в файле <sys/sem.h>. Программа-сервер создает семафоры с помощью вызова semid = semget(key, 2, 0666|IPC_CREAT);

Функция semget(2) похожа на msgget() и shmget(), но у нее есть дополнительный параметр – количество создаваемых семафоров. Дело в том, что многим процессам, использующим семафоры, требуется более одного семафора (тогда как блоки разделяемой памяти и очереди сообщений обычно существуют в единственном экземпляре). Определение уникального ключа для каждого из нескольких семафоров затруднительно, поэтому функция semget() позволяет несколько семафоров сразу. Нашему приложению понадобится два семафора. Нам понадобилось бы три семафора, если бы... Впрочем, это уже совсем другая история. Первый семафор указывает, должен ли сервер читать запись, сделанную клиентом, второй - должен ли клиент читать запись, сделанную сервером. Таким образом, мы приказываем semget() создать сразу два семафора. В случае успешного завершения функция semget() возвращает идентификатор нового массива семафоров.

Для определения состояния семафора используется структура sembuf. В структуре sembuf определено много полей (конкретный набор зависит от версии Unix-системы), из которых обязательными являются три:




    Содержание  Назад  Вперед