semctl - операции управления семафорами System V
semctl(2)
операции управления семафорами System V
ОБЗОР
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semctl(int semid, int semnum, int cmd, ...);
ОПИСАНИЕ
Вызов semctl выполняет операцию, определённую в
cmd, над набором
семафоров System V, указанном в
semid, или над семафором с номером
semnum из этого набора (семафоры нумеруются, начиная с 0).
Данный вызов имеет три или четыре аргумента, в зависимости от значения
cmd. Если аргументов четыре, то четвертый аргумент arg имеет тип union
semun. В вызывающей программе это объединение должно быть определено
следующим образом:
union semun {
int val; /* значение для SETVAL */
struct semid_ds *buf; /* буфер для IPC_STAT, IPC_SET */
unsigned short *array; /* массив для GETALL, SETALL */
struct seminfo *__buf; /* буфер для IPC_INFO
(есть только в Linux) */
};
Структура данных semid_ds определена в <sys/sem.h> следующим
образом:
struct semid_ds {
struct ipc_perm sem_perm; /* владелец и права */
time_t sem_otime; /* время последней операции semop */
time_t sem_ctime; /* время последнего изменения */
unsigned long sem_nsems; /* кол-во семафоров в наборе */
};
Структура ipc_perm определена следующим образом (значения полей
устанавливаются с помощью IPC_SET):
struct ipc_perm {
key_t __key; /* ключ, передаваемый в semget(2) */
uid_t uid; /* эффективный UID владельца */
gid_t gid; /* эффективный GID владельца */
uid_t cuid; /* эффективный UID создателя */
gid_t cgid; /* эффективный GID создателя */
unsigned short mode; /* права */
unsigned short __seq; /* порядковый номер */
};
Возможные значения cmd:
IPC_STAT
Копирует информацию из структуры данных ядра, связанной с semid, в
структуру semid_ds, расположенную по адресу arg.buf. Аргумент
semnum игнорируется. Вызывающий процесс должен иметь права на чтение
набора семафоров.
IPC_SET
Записывает значения некоторых полей структуры semid_ds, на которую
указывает arg.buf, в структуру данных ядра, связанную с этим набором
семафоров, также обновляя при этом поле sem_ctime. Обновляются следующие
поля структуры: sem_perm.uid, sem_perm.gid и (младшие 9 значащих
битов) sem_perm.mode. Эффективный UID вызывающего процесса должен
совпадать с идентификатором владельца (sem_perm.uid) или создателя
(sem_perm.cuid) набора семафоров, или вызывающий должен иметь расширенные
права. Аргумент semnum игнорируется.
IPC_RMID
Немедленно удаляет набор семафоров, пробуждая все процессы, заблокированные
в вызове semop(2) (при этом возвращается сообщение об ошибке, а errno
присваивается значение EIDRM). Эффективный идентификатор пользователя
вызывающего процесса должен совпадать с идентификатором создателя или
владельца набора семафоров, или вызывающий должен иметь расширенные
права. Аргумент semnum игнорируется.
IPC_INFO (есть только в Linux)
Возвращает параметры и информацию о системных ограничениях семафоров в
структуре, указанной в arg.__buf. Данная структура имеет тип seminfo,
который определён в <sys/sem.h>, если определён макрос
тестирования свойств _GNU_SOURCE:
struct seminfo {
int semmap; /* количество записей в карте
семафоров; не используется в ядре */
int semmni; /* максимальное количество наборов
семафоров */
int semmns; /* максимальное количество семафоров во
всех наборах семафоров */
int semmnu; /* максимальное количество структур undo
в системе; не используется в ядре */
int semmsl; /* максимальное количество семафоров в
наборе */
int semopm; /* максимальное количество операция для
semop(2) */
int semume; /* максимальное количество записей undo на
процесс; не используется в ядре */
int semusz; /* размер struct sem_undo */
int semvmx; /* максимальное значение семафора */
int semaem; /* максимальное значение, которое может
быть записано для регулирования
семафора (SEM_UNDO) */
};
Значения
semmsl,
semmns,
semopm и
semmni можно изменить через
/proc/sys/kernel/sem; подробности в
proc(5).
SEM_INFO (есть только в Linux)
Возвращает структуру seminfo, содержащую такую же информацию что и для
IPC_INFO, за исключением того, что следующие поля содержат информацию о
системных ресурсах, потребляемых семафорами: в поле semusz возвращается
количество наборов семафоров, существующих в системе; в поле semaem
возвращается общее количество семафоров во всех наборах семафоров в системе.
SEM_STAT (есть только в Linux)
Возвращает структуру semid_ds как для IPC_STAT. Однако аргумент
semid содержит не идентификатор семафора, а индекс во внутреннем массиве
ядра, который хранит информацию о всех наборах семафоров в системе.
GETALL
Возвращает значение semval (т.е. текущее значение) всех семафоров в
наборе в arg.array. Аргумент semnum игнорируется. Вызывающему процессу
нужны права на чтение набора семафоров.
GETNCNT
Возвращает значение semncnt для semnum-того семафора (т.е., число
процессов, ожидающих увеличения значения semval в semnum-ом семафоре
набора). Вызывающему процессу нужны права на чтение набора семафоров.
GETPID
Возвращает значение sempid для semnum-того семафора (т.е.,
идентификатор процесса, который последним делал вызов semop(2) для
semnum-того семафора набора). Вызывающему процессу нужны права на чтение
набора семафоров.
GETVAL
Возвращает значение semval для semnum-того семафора
набора. Вызывающему процессу нужны права на чтение набора семафоров.
GETZCNT
Возвращает значение semzcnt для semnum-того семафора (т.е., количество
процессов, ожидающих, когда значение semval semnum-того семафора
набора станет равным 0). Вызывающему процессу нужны права на чтение набора
семафоров.
SETALL
Устанавливает значение semval всех семафоров набора, используя
arg.array и изменяя также поле sem_ctime структуры semid_ds,
связанной с набором. Записи undo (см. semop(2)) очищаются для изменённых
семафоров во всех процессах. Если изменения значений семафоров приводят к
отмене блокировки в вызове semop(2) других процессов, то эти процессы
пробуждаются. Аргумент semnum игнорируется. Вызывающему процессу нужны
права на запись в набор семафоров.
SETVAL
Устанавливает значение semval равным arg.val для semnum-го семафора
набора, изменяя также поле sem_ctime в структуре semid_ds, связанной с
этим набором. Записи undo очищаются для изменённых семафоров во всех
процессах. Если изменения значений семафоров приводят к отмене блокировки в
вызове semop(2) других процессов, то эти процессы пробуждаются. Аргумент
semnum игнорируется. Вызывающему процессу нужны права на запись в набор
семафоров.
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При ошибке
semctl() возвращает -1, а переменной
errno присваивается
номер ошибки.
При успешном выполнении системный вызов возвращает положительное значение,
зависящее от cmd:
GETNCNT
значение semncnt.
GETPID
значение sempid.
GETVAL
значение semval.
GETZCNT
значение semzcnt.
IPC_INFO
самое большое значение индекса, использованного в записи внутреннего массива
ядра, содержащего информацию о всех наборах семафоров (эта информация может
использоваться в повторяющихся операциях SEM_STAT для получения
информации о всех наборах семафоров в системе).
SEM_INFO
как для IPC_INFO.
SEM_STAT
идентификатор набора семафоров, индекс которого указан в semid.
Для всех остальных значений cmd возвращается 0.
ОШИБКИ
При ошибке
errno присваиваются следующие значения:
EACCES
Аргумент cmd равен GETALL, GETPID, GETVAL, GETNCNT,
GETZCNT, IPC_STAT, SEM_STAT, SETALL или SETVAL и вызывающий
процесс не имеет достаточно прав на набор семафоров и не имеет мандата
CAP_IPC_OWNER.
EFAULT
Адрес, указанный в arg.buf или arg.array, недоступен.
EIDRM
Набор семафоров был удалён.
EINVAL
Неверное значение cmd или semid. Или: при операции SEM_STAT
значение индекса, указанное в semid, ссылается на место в массиве,
которое в данные момент не используется.
EPERM
Аргумент cmd имеет значение IPC_SET или IPC_RMID, но эффективный
идентификатор пользователя вызывающего процесса не совпадает с ID создателя
(указанного в sem_perm.cuid) или с ID владельца (указанного в
sem_perm.uid) набора семафоров, и процесс не имеет мандата
CAP_SYS_ADMIN.
ERANGE
Аргумент cmd имеет значение SETALL или SETVAL и значение,
присваиваемое semval (для какого-то семафора в наборе), меньше нуля или
больше, чем ограничение реализации SEMVMX.
СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2001, SVr4.
В POSIX.1 указано, что поле sem_nsems структуры semid_ds имеет тип
unsigned short, и это так на в большинстве других систем. Это было и в
Linux 2.2 и более ранних версиях, но начиная с Linux 2.4 это поле имеет тип
unsigned long.
ЗАМЕЧАНИЯ
Включение файлов
<sys/types.h> и
<sys/ipc.h> не
требуется в Linux или любых версий POSIX. Однако, некоторые старые
реализации требуют включения данных заголовочных файлов, и это также
требуется по SVID. В приложениях, которые нужно перенести на такие старые
системы, может потребоваться включить данных заголовочные файлы.
Операции IPC_INFO, SEM_STAT и SEM_INFO используются программой
ipcs(1) для получения информации о выделенных ресурсах. В будущем для
этого может быть задействован интерфейс файловой системы /proc.
В Linux 2.2 различные поля struct semid_ds имели тип short. В Linux
2.4 тип был изменён на long. Для задействования преимуществ этого
изменения необходима перекомпиляция программы с glibc-2.1.91 или более
поздней версией (ядро различает старые и новые вызовы по флагу IPC_64 в
аргументе cmd).
В некоторых ранних версиях glibc объединение semun определялось в
<sys/sem.h>, но в POSIX.1 требовалось, чтобы это объединение
определял вызывающий. В версиях glibc, в которых это объединение не
определено, в <sys/sem.h> определён макрос
_SEM_SEMUN_UNDEFINED.
На работу наборов семафоров и вызова semctl() влияет системное
ограничение:
SEMVMX
Максимальное значение semval: зависит от реализации (32767).
Для лучшей переносимости программ желательно всегда вызывать semctl() c
четырьмя аргументам.