Вызов 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 будет использована в примере следующего раздела.