Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
лекции иртегова / Лекция 10 - System V IPC.doc
Скачиваний:
49
Добавлен:
06.06.2015
Размер:
207.36 Кб
Скачать
      1. Semctl(2) - Примеры

В прототипе semctl(2) последний параметр указан как union. Это означает, что тип последне­го параметра зависит от значения команды cmd. На следующей странице приведены приме­ры использования различных значений cmd. Ниже показано, какие типы arg используются с различными командами:

. int val;

SETVAL Эта команда устанавливает значение отдельного семафора в наборе.

 . struct semid_ds *buf;

IPC_STAT Эта команда копирует состояние набора семафоров в буфер buf.

IPC_SET Эта команда устанавливает значения хозяина, группы и прав доступа для набо­ра семафоров.

 . ushort *array;

GETALL Эта команда получает значения всех семафоров в наборе и поме­щает их в массив, на который указывает array.

SETALL Устанавливает все семафоры из набора в значения, которые хранят­ся в массиве array.

. arg не используется

GETVAL Эта команда получает значение семафора с индексом semnum.

GETPID Эта команда получает идентификатор процесса, который совершал по­следнюю операцию над семафором с индексом semnum.

GETNCNT Эта команда получает количество процессов, ожидающих увеличе­ния значения семафора по сравнению с текущим.

GETZCNT Эта команда получает количество процессов, ожидающих, пока значение семафора не станет 0.

IPC_RMID Эта команда удаляет набор семафоров и его идентификатор. Если какие-то процессы были заблокированы в операциях с этим набором, во всех этих про­цессах соответствующие вызовы semop(2) вернут ошибку EIDRM.

                        semctl(2) - ПРИМЕРЫ

. описания и системный вызов для создания набора семафоров

  #include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#define ANY 0int semid, rtn;struct semid_ds ds;ushort us[5], init_us[5] = { 0, 6, 7, 1, 4 };...semid = semget(key, 5, IPC_CREAT | 0660);

. инициализировать один семафор из набора

          semctl(semid, 2, SETVAL, 7);

. получить значение одного семафора из набора

     /* такой же формат для GETNCNT, GETZCNT, GETPID */rtn = semctl (semid, 2, GETVAL, ANY);

. инициализировать все семафоры в наборе

          semctl (semid, ANY, SETALL, init_us);

. получить все значения семафоров в наборе

          semctl (semid, ANY, GETALL, us);

. изменить хозяина

          /* также изменяются права доступа */semctl (semid, ANY, IPC_STAT, &ds);ds.sem_perm.uid = 51; /* new uid */semctl (semid, ANY, IPC_SET, &ds);

. удалить набор семафоров

          semctl (semid, ANY, IPC_RMID, ANY);

      1. Инициализировать и удалить семафор - Пример

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

32-37 Если эта программа создала набор семафоров, инициализировать его в 1. Как правило, набор семафоров должен быть удален перед выходом из программы, если его инициализация не удалась, но это здесь не показано.

54-60 Cоздатель набора семафоров может удалить его. В нашей программе, по соглаше­нию, удалением семафоров занимается тот же процесс, который их создал. Обратите внима­ние на использование "пустых" аргументов в тех местах, где соответствующие параметры системных вызовов не используются. Функция sleep(3C) задерживает удаление сема­фора на 5 секунд, так что другая программа может продолжать работу с ним.

Файл: semdemo.cИНИЦИАЛИЗИРОВАТЬ И УДАЛИТЬ СЕМАФОР - ПРИМЕР1 #include <unistd.h>2 #include <stdlib.h>3 #include <sys/types.h>4 #include <sys/ipc.h>5 #include <sys/sem.h>6 #include <stdio.h>7 #define  DUMMY  08 #define  COUNT  4910 main(int argc, char *argv[])11 {...32  if (creator) {/* initialize semaphore */33  if (semctl(semid, 0, SETVAL, 1) == -1) {34  perror(argv[0]);35  exit(2);36  }37  }...54  if (creator) {55  sleep(5);56  if(semctl(semid,DUMMY,IPC_RMID,DUMMY) == -1) {57  perror(argv[0]);58  exit(5);59  }60  }61  return(0);62 }

Операции над семафорами

Системный вызов semop(2) производит операции над одним или более семафорами из на­бора. Операции увеличивают или уменьшают значение семафора на заданную величину, или ожидают, пока семафор не станет нулевым.

Аргументы этого системного вызова таковы:

semid Идентификатор набора семафоров.

sops Адрес массива с элементами типа struct sembuf. Каждый элемент задает одну опера­цию над одним семафором. По этому адресу должно размещаться nsops таких структур. Эта структура определена следующимобразом:

      sys/sem.h:
      struct sembuf {ushort sem_num; /* semaphore */short sem_op;   /* semaphore operation */short sem_flg;  /* operation flags */};

Поля этой структуры имеют следующий смысл:

sem_num Индекс семафора, над которым производится операция.

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

Если sem_op отрицательно, и его абсолютное значение больше текущего значения семафора, операция обычно блокируется. Иначе, из семафора просто вычитает­ся абсолютное значение этого поля (WAIT).

Если sem_op равен нулю, операция блокируется, пока семафор не станет нулевым.

sem_flg Это поле задает дополнительные флаги. Нулевое значение означает, что не задано никаких флагов.Допустимы следующие флаги, объединяемые побитовым ИЛИ:

IPC_NOWAIT Если установлен этот флаг, и операция должна была бы привести к блокировке, semop(2) возвращает неуспех. Этот флаг может быть использо­ван для анализа и изменения значения семафора без блокировки.

SEM_UNDO Если этот флаг установлен, при завершении процесса (как по exit(2), так и по сигналу), операция будет отменена. Это защищает от посмертной блокировки ресурса процессом, который ненормально завершился, не успев освободить ресурс.

Использование SEM_UNDO отменяет операцию над семафором, но не обеспечивает, что ре­сурс, защищаемый этим семафором, остался в согласованном состоянии после завершения процесса.

Кроме того, нужно иметь в виду, что отмена операций реализована в виде счетчика, в кото­ром накапливаются все значения, добавляемые и вычитаемые процессом при операциях над данным семафором. При завершении процесса этот счетчик просто вычитается из текущего значения семафора. Из этого описания должно быть ясно, что если вы используете флаг SEM_UNDO, его необходимо использовать при всех операциях над этим семафором. Если вы указываете SEM_UNDO только при операциях LOCK, но не при UNLOCK, счетчик отме­ны может просто переполниться, а его применение к семафору может привести к нежела­тельным результатам.

При выполнении операции над несколькими семафорами, значения семафоров не меня­ются, пока не окажется, что все требуемые операции могут быть успешно выполнены. При этом, поведение системы в случае, когда набор операций содержит несколько разных операций над одним и тем же семафором, не стандартизовано. Разные реализации POSIX могут интерпретировать такой набор по разному.

nsops Количество структур в массиве, на который указывает sops. nsops должен всегда быть больше или равен 1. Параметр prctl(1) process.max-sem-ops ограничивает максимальное количество операций в одном наборе.