Системное программирование в UNIX средствами Free Pascal

       

Вызов semget аналогичен вызову msgget.


uses ipc;
Function semget(key:Tkey; nsems:longint; permflags:longint):longint;
Вызов semget аналогичен вызову msgget. Дополнительный параметр nsems задает требуемое число семафоров в наборе семафоров; это важный момент – семафорные операции в
System V IPC приспособлены для работы с наборами семафоров, а не с отдельными объектами семафоров. На рис. 8.2 показан набор семафоров. Ниже увидим, что использование целого набора семафоров усложняет интерфейс процедур работы с семафорами.

Индекс 0
Индекс 1


Индекс 2
Индекс 3
semid
semval = 2
semval = 4
semval = 1
semval = 3

nsems=4

Рис.8.2. Набор семафоров
Значение, возвращаемое в результате успешного вызова semget, является идентификатором набора семафоров (semaphore set identifier), который ведет себя почти так же, как идентификатор очереди сообщений. Идентификатор набора семафоров обозначен на рис. 8.2 как semid. Следуя обычной практике, индекс семафора в наборе может принимать значения от 0 до nsems-1.
С каждым семафором в наборе связаны следующие значения:
semval        Значение семафора, положительное целое число. Устанавливается при помощи системных вызовов работы с семафорами, то есть к значениям семафоров нельзя получить прямой доступ из программы, как к другим объектам данных
sempid        Идентификатор процесса, который последним работал с семафором
semcnt        Число процессов, ожидающих увеличения значения семафора
semzcnt      Число процессов, ожидающих обнуления значения семафора


uses ipc;
Function semctl(semid:longint; sem_num:longint; command:longint;
                var ctl_arg:tsemun):longint;
Из определения видно, что функция semctl намного сложнее, чем msgctl. Параметр semid должен быть допустимым идентификатором семафора, возвращенным вызовом semget. Параметр command имеет тот же смысл, что и в вызове msgctl,
– задает требуемую команду. Команды распадаются на три категории: стандартные команды управления средством межпроцессного взаимодействия (такие как IPC_STAT); команды, которые воздействуют только на один семафор; и команды, действующие на весь набор семафоров. Все доступные команды приведены в табл. 8.1.
Таблица 8.1. Коды функций вызова semctl
Стандартные функции межпроцессного взаимодействия
IPC_STAT        Поместить информацию о статусе в поле ctl_arg.stat
IPC_SET          Установить данные о владельце/правах доступа
IPC_RMID        Удалить набор семафоров из системы
Операции над одиночными семафорами
(относятся к семафору sem_num, значение возвращается вызовом semctl)
GETVAL            Вернуть значение семафора (то есть setval)
SETVAL            Установить значение семафора равным ctl_arg.val
GETPID            Вернуть значение sempid
GETNCNT          Вернуть semncnt (см. выше)
GETZCNT          Вернуть semzcnt (см. выше)
Операции над всеми семафорами
GETALL            Поместить все значения setval в массив ctl_arg.array
SETALL            Установить все значения setval из массива ctl_arg.array
Параметр sem_num используется со второй группой возможных операций вызова semctl для задания определенного семафора. Последний параметр ctl_arg является объединением
(записью с вариантами), определенным следующим образом:
PSEMun = ^TSEMun;
TSEMun = record
  case longint of
    0 : (val    : longint);
    1 : (buf    : PSEMid_ds);
    2 : (arr    : PWord);
    3 : (padbuf : PSeminfo);
    4 : (padpad : pointer);
  end;
Каждый элемент объединения представляет некоторый тип значения, передаваемого вызову semctl при выполнении определенной команды. Например, если значение command равно SETVAL, то будет использоваться элемент ctl_arg.val.


Одно из важных применений функции setval заключается в установке начальных значений семафоров, так как вызов semget не позволяет процессу сделать это. Приведенная в качестве примера функция initsem может использоваться для создания одиночного семафора и получения связанного с ним идентификатора набора семафоров. После создания семафора (если семафор еще не существовал) функция semctl присваивает ему начальное значение, равное единице.
{$i pv.inc}
(* Функция initsem - инициализация семафора *)
function initsem(semkey:tkey):longint;
var
  status, semid:longint;
  arg:tsemun;
begin
  status := 0;
  semid := semget (semkey, 1,
                  SEMPERM or IPC_CREAT or IPC_EXCL);
  if semid = -1 then
  begin
    if ipcerror = Sys_EEXIST then
      semid := semget (semkey, 1, 0);
  end
  else
    (* если семафор создается ... *)
  begin
    arg.val := 1;
    status := semctl (semid, 0, SETVAL, arg);
  end;
  if (semid = -1) or (status = -1) then
  begin
    perror ('ошибка вызова initsem');
    initsem:=-1;
    exit;
  end;
  (* Все в порядке *)
  initsem:=semid;
end;
Включаемый файл pv.inc содержит следующие определения:
(* Заголовочный файл для примера работы с семафорами *)
const
  SEMPERM=6 shl 6{0600};
Функция initsem будет использована в примере следующего раздела.

Содержание раздела