#include <sys/sem.h>
int semctl (int semid, int sem_num, int command, union semun ctl_arg);
Из определения видно, что функция 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 является объединением, определенным следующим образом:
|
|
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
};
Каждый элемент объединения представляет некоторый тип значения, передаваемого вызову semctl при выполнении определенной команды. Например, если значение command равно SETVAL, то будет использоваться элемент ctl_arg.val.
Одно из важных применений функции setval заключается в установке начальных значений семафоров, так как вызов semget не позволяет процессу сделать это. Приведенная в качестве примера функция initsem может использоваться для создания одиночного семафора и получения связанного с ним идентификатора набора семафоров. После создания семафора (если семафор еще не существовал) функция semctl присваивает ему начальное значение равное единице.
/* Функция initsem - инициализация семафора */
#include "pv.h"
int initsem(key_t semkey)
{
int status = 0, semid;
if ((semid = semget(semkey, 1, SEMPERM|IPC_CREAT|IPC_EXCL)) == -1)
{
if(errno = EEXIST)
semid = semget(semkey, 1, 0);
}
else /* Если семафор создается */
{
union semun arg;
arg.val = 1;
status = semctl(semid, 0, SETVAL, arg);
}
if(semid == -1|| status == -1)
{
perror("Ошибка вызова initsem");
return (-1);
}
/* Все в порядке */
return (semid);}
Включаемый файл pv. h содержит следующие определения:
/* Заголовочный файл для примера работы с семафорами */
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
#define SEMPERM 0600
#define TRUE 1
#define FALSE 0
typedef union _semun
{
int val;
struct semid_ds *buf;
ushort *array;
} semun;