Семафоры

Семафор – особая структура, содержащая число большее или равное нулю и управляющая цепочкой процессов, ожидающих особого состояния на данном семафоре. Хотя они и кажутся очень простыми, семафоры – это очень мощное средство, а потому, на самом деле, весьма сложное.

Семафоры используются для контроля доступа к ресурсам: число в семафоре представляет собой количество процессов, которые могут получить доступ к данным. Каждый раз, когда процесс обращается к данным, значение в семафоре, должно быть уменьшено на единицу, и увеличено, когда работа с данными будет прекращена. Если ресурс эксклюзивный, то есть к данным должен иметь доступ только один процесс, то начальное значение в семафоре следует установить единицей.

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

Пусть имеется буфер, в который несколько процессов S1,...,Sn могут записывать, и только один процесс L может из него считывать. Также операции нельзя выполнять одновременно (в данный момент времени только один процесс должен оперировать с буфером). Очевидно, что процессы Si могут писать всегда, когда буфер не полон, а процесс L может читать, когда буфер не пуст.

Таким образом, необходимо три семафора: один управляет доступом к буферу, а два других следят за числом элементов в нём.

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

В библиотеке C, в SysV семафор создаёт функция semget(2)

int semget(key_t key, int nsems, int semflg)

где key – IPC ключ, nsems – число семафоров, которое нежно создать, и semflg – права доступа, закодированные в 12 бит: первые три бита отвечают за режим создания, остальные девять – права на запись и чтение для пользователя, группы и остальных. Таким образом, SysV создаёт сразу несколько семафоров, что уменьшает код.

 

--------------------------------------------------------------

#include <stdio.h>

#include <stdlib.h>

#include <linux/types.h>

#include <linux/ipc.h>

#include <linux/sem.h>

 

int main(void)

{

key_t key;

int semid;

 

key = ftok("/etc/fstab", getpid());

 

/* создать только один семафор: */

semid = semget(key, 1, 0666 | IPC_CREAT);

 

return 0;

}

--------------------------------------------------------------

 

Управление семафором происходит с помощью функции semctl(2),

 

int semctl(int semid, int semnum, int cmd, ...),

 

которая выполняет действие cmd на наборе семафоров semid или (если требуется командой) на одном семафоре с номером semnum.

 

В зависимости от команды, может понадобится указать ещё один аргумент следующего типа:

{

union semun

int val; /* значение для SETVAL */

struct semid_ds *buf; /* буферы для IPC_STAT, IPC_SET */

unsigned short *array; /* массивы для GETALL, SETALL */

/* часть, особенная для Linux: */

struct seminfo *__buf; /* буфер для IPC_INFO */

};

 

Чтобы изменить значение семафора, используется директива SETVAL, новое значение должно быть указано в semun.

 

[...]

 

/* создать только один семафор */

semid = semget(key, 1, 0666 | IPC_CREAT);

 

/* в семафоре 0 установить значение 1 */

arg.val = 1;

semctl(semid, 0, SETVAL, arg);

 

[...]

 

Удаление семафора и освобождение структуры, использовавшейся для управления им выполняет директива IPC_RMID. Она удаляет семафор и посылает сообщение об этом всем процессам, ожидающим доступа к ресурсу. Последний раз изменим программу:

 

[...]

 

/* в семафоре 0 установить значение 1 */

arg.val = 1;

semctl(semid, 0, SETVAL, arg);

 

/* удалить семафор */

semctl(semid, 0, IPC_RMID);

 

[...]

 

Использовать семафор можно с помощью процедуры semop(2),

 

int semop(int semid, struct sembuf *sops, unsigned nsops);

 

здесь semid – идентификатор набора семафоров, sops – массив, содержащий операции, которые необходимо произвести, nsops – число этих операций. Каждая операция представляется структурой sembuf.

 

unsigned short sem_num; short sem_op; short sem_flg;

 

т.е номером семафора в множестве (sem_num), операцией (sem_op) и флагом, устанавливающим режим ожидания; пока он будет нулём.

Операции, которые можно указать, являются целыми числами и подчиняются следующим правилам:

1. sem_op < 0

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

2. sem_op = 0. Процесс спит пока значение в семафоре не достигнет нуля.

3. sem_op > 0 Значение sem_op добавляется к значению в семафоре, используемый ресурс освобождается.

Следующая программа представляет пример использования семафоров, реализуя предыдущий пример с буфером для чего создается пять процессов W и один процесс R. Процессы W будут пытаться получить доступ к ресурсу (буферу), закрывая его через семафор, и, если буфер не полон, будут класть в него элемент и освобождать ресурс. Процесс R будет закрывать ресурс, брать из него элемент, если буфер не пуст, и разблокировать ресурс.

Чтение и запись в буфер на самом деле ненастоящие: так происходит потому, что каждый процесс выполняется в своей собственной области памяти и не может обращаться к памяти другого процесса. Это делает настоящее управление буфером шестью процессами невозможным, так как каждый процесс будет видеть свою копию буфера.

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








Дата добавления: 2015-03-26; просмотров: 671;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.013 сек.