ИМЯ
semctl -
операции
управления
семафорами
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
содержит
не
идентификатор
семафора, а
индекс во
внутреннем
массиве
ядра,
который
хранит
информацию
о всех
наборах
семафоров
в системе.
- SEM_STAT_ANY
(есть
только в Linux-specific,
начиная с Linux
4.17)
- Возвращает
структуру
seminfo,
содержащую
информацию
как у SEM_STAT.
Однако sem_perm.mode
не
проверяется
на
доступность
чтения для
semid, что
означает,
что эту
операцию
может
выполнять
пользователь
(как и
любой
пользователь,
который
может
прочитать
эту же
информацию
из /proc/sysvipc/sem).
- GETALL
- Возвращает
значение
semval (т.е.
текущее
значение)
всех
семафоров
в наборе в
arg.array.
Аргумент
semnum
игнорируется.
Вызывающему
процессу
нужны
права на
чтение
набора
семафоров.
- GETNCNT
- Возвращает
значение
semncnt для
semnum-того
семафора
(т.е., число
процессов,
ожидающих
увеличения
значения
semval в semnum-ом
семафоре
набора).
Вызывающему
процессу
нужны
права на
чтение
набора
семафоров.
- GETPID
- Возвращает
значение
sempid для
semnum-того
семафора
набора. Это
PID процесса,
который
последним
выполнял
операцию с
этим
семафором
(но
смотрите
ЗАМЕЧАНИЯ).
Вызывающему
процессу
нужны
права на
чтение
набора
семафоров.
- 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_STAT_ANY
для
получения
информации
о всех
наборах
семафоров
в системе).
- SEM_INFO
- как для IPC_INFO.
- SEM_STAT
- идентификатор
набора
семафоров,
индекс
которого
указан в
semid.
- SEM_STAT_ANY
- как у SEM_STAT.
Для всех
остальных
значений cmd
возвращается
0.
ОШИБКИ
При
ошибке errno
присваиваются
следующие
значения:
- EACCES
- Аргумент
cmd равен GETALL,
GETPID, GETVAL, GETNCNT, GETZCNT,
IPC_STAT, SEM_STAT, SEM_STAT_ANY, SETALL
или SETVAL и
вызывающий
процесс не
имеет
требуемых
прав на
набор
семафоров
и не имеет
мандата
CAP_IPC_OWNER в
пользовательском
пространстве
имён,
которое
управляет
своим
пространством
имён IPC.
- 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-2008, 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
четырьмя
аргументам.
Значение
sempid
В POSIX.1
значение
sempid
определено
как «ID
процесса
последней
операции»
над
семафором,
и явно
отмечено,
что это
значение
устанавливается
успешным
вызовом semop(2),
подразумевая,
что больше
никто не
изменяет
sempid.
Одни
реализации
следуют
требованиям,
указанным
в POSIX.1, а другие
нет (вина
здесь,
вероятно,
лежит на POSIX.1,
так как ему
не удастся
охватить
поведение
всех
существующих
реализаций).
Также,
разные
реализации
обновляют
sempid другими
операциями,
обновляющими
значение
семафора:
SETVAL и SETALL, а
также
изменение
семафора,
выполняемое
при
завершении
процесса
как
следствие
использования
флага SEM_UNDO
(смотрите
semop(2)).
Linux также
обновляет
sempid при
операциях
SETVAL и
регулировки
семафора.
Однако,
непоследовательно,
ранние
версии Linux по 4.5
включительно
не
обновляли
sempid при
операциях
SETALL. Это было
исправлено
в Linux 4.6.