Операционная система UNIX - страница 115

стр.

1. Значение семафора должно быть доступно различным процессам. Поэтому семафор находится не в адресном пространстве процесса, а в адресном пространстве ядра.

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

Таким образом семафоры являются системным ресурсом, действия над которым производятся через интерфейс системных вызовов.

Семафоры в System V обладают следующими характеристиками:

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

□ Каждое из этих чисел может принимать любое неотрицательное значение в пределах, определенных системой (а не только значения 0 и 1).

Для каждой группы семафоров (в дальнейшем мы будем называть группу просто семафором) ядро поддерживает структуру данных >semid_ds, включающую следующие поля:

>struct ipc_perm sem_permОписание прав доступа
>struct sem *sem_baseУказатель на первый элемент массива семафоров
>ushort sem_nsemsЧисло семафоров в группе
>time_t sem_otimeВремя последней операции
>time_t sem_ctimeВремя последнего изменения

Значение конкретного семафора из набора хранится во внутренней структуре >sem:

>ushort semvalЗначение семафора
>pid_t sempidИдентификатор процесса, выполнившего последнюю операцию над семафором
>ushort semncntЧисло процессов, ожидающих увеличения значения семафора
>ushort semzcntЧисло процессов, ожидающих обнуления семафора

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

Для получения доступа к семафору (и для его создания, если он не существует) используется системный вызов semop(2):

>#include

>#include

>#include


>int semget(key_t key, int nsems, int semflag);

В случае успешного завершения операции функция возвращает дескриптор объекта, в случае неудачи - -1. Аргумент >nsems задает число семафоров в группе. В случае, когда мы не создаем, а лишь получаем доступ к существующему семафору, этот аргумент игнорируется. Аргумент >semflag определяет права доступа к семафору и флажки для его создания (>IPC_CREAT, >IPC_EXCL).

После получения дескриптора объекта процесс может производить операции над семафором, подобно тому, как после получения файлового дескриптора процесс может читать и записывать данные в файл. Для этого используется системный вызов semop(2):

>#include

>#include

>#include


>int semop(int semid, struct sembuf *semop, size_t nops);

В качестве второго аргумента функции передается указатель на структуру данных, определяющую операции, которые требуется произвести над семафором с дескриптором >semid. Операций может быть несколько, и их число указывается в последнем аргументе >nops. Важно, что ядро обеспечивает атомарность выполнения критических участков операций (например, проверка значения — изменение значения) по отношению к другим процессам.

Каждый элемент набора операций >semop имеет вид:

>struct sembuf {

> short sem_num; /* номер семафора в группе */

> short sem_op;  /* операция */

> short sem_flg; /* флаги операции */

>}

UNIX допускает три возможные операции над семафором, определяемые полем >semop:

1. Если величина >semop положительна, то текущее значение семафора увеличивается на эту величину.

2. Если значение >semop равно нулю, процесс ожидает, пока семафор не обнулится.