int semop(int semid,struct sembuf *sops,unsigned nsops);
int semtimedop(int semid,struct sembuf *sops,unsigned nsops,struct timespec *timeout);
ОПИСАНИЕ
Функция производит операции над выбранными элементами из набора семафоров
semid.
Каждый из элементов
nsops
в массиве
sops
определяет операцию, производимую над семафором в структуре
struct sembuf,
состоящей из полей:
short sem_num;
/* semaphore number: 0 = first */
short sem_op;
/* semaphore operation */
short sem_flg;
/* operation flags */
Флаги в
sem_flg
могут иметь значения
IPC_NOWAIT
и
SEM_UNDO.
Если стоит флаг
SEM_UNDO,
то будет выполнена обратная операция при закрытии процесса.
Обратная операция будет выполнена только при условии выполнения предыдущей операции.
Каждая операция выполняется над семафором
sem_num
набора, где первый семафор набора имеет номер
0,
и его значение равно одному из трех следующих:
если
sem_op
является положительным целым числом, то оно добавляется к
semval.
Если для операции стоит флаг
SEM_UNDO,
то система изменяет счетчик обратных операций для
этого семафора.
Операция все время производится и поэтому никогда не может перейти в режим ожидания.
Вызывающий процесс должен иметь права на изменение набора.
Если
sem_op
равен нулю, то процесс должен иметь права на чтение набора.
Если
semval
равен нулю, то операция производится без наличия дополнительных прав.
Иначе, если флаг
IPC_NOWAIT
стоит в поле семафора
sem_flg,
системный вызов не выполняется (производятся все обратные операции), а
errno
присваивается значение
EAGAIN.
В другом случае
semzcnt
увеличивается на единицу, а процесс переходит в режим ожидания
до того момента, когда
*
semval
становится равным 0, а значение
semzcnt
увеличивается.
*
Набор семафоров удален, системный вызов не выполняется, а
errno
присваивается значение
EIDRM.
*
Вызывающий процесс получает сигнал, который должен быть обработан; когда это
происходит, значение
semzcnt
увеличивается, а системный вызов не выполняется, а переменной
errno
присваивается значение
EINTR.
*
Лимит времени, определенный
timeout
в вызове
semtimedop
истек: системный вызов выдает ошибку, а переменная
errno
устанавливается в
EAGAIN.
Если
sem_op
меньше нуля, то процесс должен иметь права на изменение набора.
Если
semval
больше или равен абсолютному значению
sem_op,
то абсолютное значение
sem_op
приравнивается к
semval.
Если для этой операции установлен флаг
SEM_UNDO,
то счетчик обратных операций для этого семафора обновляется,
а выполнение операции продолжается.
Иначе, если флаг
IPC_NOWAIT
стоит в поле
sem_flg,
системный вызов не выполняется (производятся все обратные операции), а
errno
присваивается значение
EAGAIN.
В ином случае
semncnt
увеличивается на единицу, а процесс переходит в режим ожидания
до того момента, когда
*
semval
становится больше или равно абсолютному значению
sem_op,
значение
semncnt
уменьшается, абсолютное значение
sem_op
приравнивается к
semval,
и если флаг
SEM_UNDO
установлен для этой операции, то система обновляет счетчик обратных
операций для этого семафора.
*
При удалении набора семафоров системный вызов не выполняется, а переменной
errno
присваивается значение
EIDRM.
*
Вызывающий процесс получает сигнал, после чего
semncnt
увеличивается, системный вызов не выполняется, а переменной
errno
присваивается значение
EINTR.
*
Лимит времени, определенный
timeout
в вызове
semtimedop
истек: системный вызов выдает ошибку, а переменная
errno
устанавливается в
EAGAIN.
В случае выполнения
sempid,
являющейся членом структуры,
sem
приобретает значение идентификатора процесса.
Так или иначе,
sem_otime
и
sem_ctime
устанавливаются на текущее время.
Функция
semtimedop
ведет себя идентично функции
semop
за исключением того, что в случаях, когда вызывающий процесс будет спать,
длительность этого сна ограничена количеством времени, определенного структурой
timespec
чей адрес передается в параметре
timeout.
Если достигнут указанный лимит времени, то системный вызов выдает ошибку, а
errno
устанавливается в
EAGAIN
(и ни одна из операций в
sops
не выполняется).
Если параметр
timeout
равен
NULL,
то
semtimedop
ведет себя точно так же, как и
semop.
ВОЗВРАЩАЕМЫЕ ЗНАЧЕНИЯ
При успешном выполнении системного вызова возвращаемое значение равно
нулю,
в случае ошибки оно равно
-1,
а переменной
errno
присваивается номер ошибки.
НАЙДЕННЫЕ ОШИБКИ
В случае ошибки
errno
будет присвоено одно из следующих значений:
E2BIG
значение аргумента
nsops
больше, чем значение
SEMOPM,
указывающее на максимальное количество операций для системного вызова.
EACCES
Вызывающий процесс не имеет прав на доступ к набору семафоров.
EAGAIN
Операция не может быть исполнена немедленно и либо
IPC_NOWAIT
было указан в его
sem_flg
или истекло время лимита, определенное в
timeout.
EFAULT
Адрес, указанный либо в
sops
либо в
timeout
не доступен.
EFBIG
Для некоторых операций значение
sem_num
меньше нуля или больше или равно количеству семафоров в наборе.
EIDRM
Набор семафоров был удален.
EINTR
Процесс, находясь в режиме ожидания, получает сигнал, который должен быть обработан.
EINVAL
Набор семафоров не существует, или значение
semid
меньше нуля или
nsops
имеет отрицательное значение.
ENOMEM
Для выполнения некоторых операций в поле
sem_flg
стоит флаг
SEM_UNDO,
и система не имеет достаточно памяти для записи структуры выполнения
обратных операций.
ERANGE
Для некоторых операций значение
semop+semval
является большим, чем
SEMVMX,
максимальное значение
semval,
заданное в ядре.
ЗАМЕЧАНИЯ
Структуры
sem_undo
процесса не наследуются его дочерними процессами при
выполнении вызова
fork(2).
Но они наследуются процессом, создающимся при выполнении системного вызова
execve(2).
Ниже приведены лимиты ресурсов наборов, влияющие на вызов
semop:
SEMOPM
Наибольшее количество операций для одного вызова
semop
зависит от существующих прав.
SEMVMX
Наибольшее значение для
semval:
зависит от реализации (32767).
Нет существенных ограничений
максимального значения
(SEMAEM),
максимального количества системных структур обратных операций
(SEMMNU)
и максимального количества системных параметров для структур обратных операций
каждого процесса.
НАЙДЕННЫЕ ОШИБКИ
Для каждого процесса в системе есть структура
sem_undo,
в которой содержится информация о каждом измененном семафоре.
При завершении процесса память, занимаемая этими структурами, освобождается.
Существует одна проблема с обратными операциями: они не соответствуют базовому набору
операций над массивом семафоров.
Должен ли процесс быть в режиме ожидания во время его завершения, или все обратные операции
должны быть совершены с флагом
IPC_NOWAIT.
В настоящий момент применяются именно такие флаги, а обратные операции,
которые не исполняются сразу же, попросту игнорируются.
СООТВЕТСТВИЕ СТАНДАРТАМ
SVr4, SVID. SVr4 описывает дополнительные коды ошибок EINVAL, EFBIG,
ENOSPC.