Provided by: manpages-ru-dev_4.19.0-7_all bug

ИМЯ

       semop, semtimedop - операции с семафорами System V

LIBRARY

       Standard C library (libc, -lc)

СИНТАКСИС

       #include <sys/sem.h>

       int semop(int semid, struct sembuf *sops, size_t nsops);
       int semtimedop(int semid, struct sembuf *sops, size_t nsops,
                      const struct timespec *_Nullable timeout);

   Требования макроса тестирования свойств для glibc (см. feature_test_macros(7)):

       semtimedop():
           _GNU_SOURCE

ОПИСАНИЕ

       С каждым семафором в наборе семафоров System V связаны следующие значения:

           unsigned short  semval;   /* semaphore value */
           unsigned short  semzcnt;  /* # waiting for zero */
           unsigned short  semncnt;  /* # waiting for increase */
           pid_t           sempid;   /* PID of process that last
                                        modified the semaphore value */

       Вызов  semop()  производит  операции  над выбранными семафорами из набора семафоров semid.
       Каждый из элементов nsops  в  массиве,  указанном  в  sops  является  структурой,  которой
       задаётся  операция, выполняемая над отдельным семафором. Элементы этой структуры имеют тип
       struct sembuf, который содержит поля:

           unsigned short sem_num;  /* номер семафора */
           short          sem_op;   /* операция над семафором */
           short          sem_flg;  /* флаги операции */

       Флаги в sem_flg могут иметь значения IPC_NOWAIT и SEM_UNDO. Если указан флаг SEM_UNDO,  то
       при завершении процесса будет выполнена откат операции.

       Набор  операций из sops выполняется в порядке появления в массиве и является атомарным, то
       есть выполняются  или  все  операции,  или  ни  одной.  Поведение  системного  вызова  при
       обнаружении  невозможности  немедленного  выполнения  операций  зависит  от  наличия флага
       IPC_NOWAIT в полях sem_flg отдельных операций, как это описано далее.

       Каждая операция выполняется над sem_num-тым семафором из набора, где первый семафор  имеет
       номер 0. Есть три типа операций, различающихся значением sem_op.

       If  sem_op  is  a  positive  integer, the operation adds this value to the semaphore value
       (semval).  Furthermore, if SEM_UNDO is specified for this operation, the system  subtracts
       the  value  sem_op from the semaphore adjustment (semadj)  value for this semaphore.  This
       operation can always proceed—it never forces a thread to wait.  The calling  process  must
       have alter permission on the semaphore set.

       Если значение sem_op равно нулю, то процесс должен иметь права на чтение набора семафоров.
       Эта операция «ожидания нуля»: если semval равно нулю, то операция может выполнится  сразу.
       Иначе,  если  в  поле  семафора  sem_flg  указан флаг IPC_NOWAIT, то semop() завершается с
       ошибкой и errno присваивается значение EAGAIN (и ни одна операция из sops не выполняется).
       Или  же  semzcnt  (счётчик  нитей, ожидающих пока значение семафора не сравнялось с нулём)
       увеличивается на единицу, а нить переходит в режим ожидания пока не случится одно из:

       •  Значение semval станет равным 0, тогда значение semzcnt уменьшается.

       •  Набор семафоров удалится: semop() завершается с ошибкой, а errno присваивается значение
          EIDRM.

       •  Вызывающая  нить  получит  сигнал: значение semncnt уменьшается и semop() завершается с
          ошибкой, а errno присваивается значение EINTR.

       Если значение sem_op меньше нуля, то  процесс  должен  иметь  права  на  изменение  набора
       семафоров.  Если значение semval больше или равно абсолютному значению sem_op, то операция
       может выполнятся сразу: абсолютное значение sem_op вычитается из semval, и, если для  этой
       операции установлен флаг SEM_UNDO, система добавляет абсолютное значение sem_op к значению
       регулировки (semadj) семафора. Если абсолютное значение sem_op больше semval, и в  sem_flg
       указан IPC_NOWAIT, то semop() завершается с ошибкой, а errno присваивается значение EAGAIN
       (и ни одна операция из sops не  выполняется).  Иначе  semncnt  (счётчик  нитей,  ожидающих
       увеличения  значения семафора) увеличивается на единицу, а нить переходит в режим ожидания
       пока не случится одно из:

       •  semval становится больше или равно абсолютному значению sem_op:  операция  продолжается
          как описано выше.

       •  Набор   семафоров   удалится  из  системы:  semop()  завершается  с  ошибкой,  а  errno
          присваивается значение EIDRM.

       •  Вызывающая нить получит сигнал: значение semncnt уменьшается и  semop()  завершается  с
          ошибкой, а errno присваивается значение EINTR.

       При  успешном  выполнении  значение  sempid для каждого семафора, указанного в массиве, на
       который указывает sops, устанавливается равным идентификатору вызывающего процесса.  Также
       sem_otime присваивается значение текущего времени.

   semtimedop()
       Системный  вызов  semtimedop()  ведёт  себя идентично semop(), за исключением  того, что в
       случаях, когда вызывающая нить будет спать, длительность этого сна ограничена  количеством
       времени,  определяемым  структурой  timespec,  чей  адрес  передаётся в аргументе timeout.
       Данное значение интервала будет округлено до точности системных часов,  а  из-за  задержки
       при  планировании  в  ядре  блокирующий  интервал  будет  немного  больше.  Если достигнут
       указанный лимит времени, то semtimedop() завершится с ошибкой, а errno  устанавливается  в
       EAGAIN  (и  ни  одна  из  операций в sops не выполняется). Если значение аргумента timeout
       равно NULL, то semtimedop() ведёт себя аналогично semop().

       Заметим, что если semtimedop() прерывается сигналом, то вызов завершается с ошибкой EINTR,
       а содержимое timeout не изменяется.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

       On  success,  semop()   and  semtimedop()   return 0.  On failure, they return -1, and set
       errno to indicate the error.

ОШИБКИ

       E2BIG  Значение аргумента nsops больше SEMOPM, максимального количества операций,  которое
              может выполнить один системный вызов.

       EACCES Вызывающий  процесс  не имеет прав, требуемых для выполнения указанных операций над
              семафорами, и не имеет мандата CAP_IPC_OWNER, который управляет  его  пространством
              имён IPC.

       EAGAIN Операция  не  может  быть  выполнена  немедленно  и,  либо  IPC_NOWAIT был указан в
              sem_flg, либо истекло время лимита, определённое в timeout.

       EFAULT Адрес, указанный в sops или timeout, не доступен.

       EFBIG  Для некоторых операций значение sem_num меньше нуля или больше или равно количеству
              семафоров в наборе.

       EIDRM  Набор семафоров был удалён.

       EINTR  Нить, находясь в режиме ожидания, получила сигнал; смотрите signal(7).

       EINVAL Набор  семафоров  не существует, или значение semid меньше нуля, или nsops имеет не
              положительное значение.

       ENOMEM Для некоторых операций в поле sem_flg задан  флаг  SEM_UNDO,  и  система  не  может
              выделить достаточно памяти для структуры откатов.

       ERANGE Для  некоторых  операций  sem_op+semval  больше  чем SEMVMX, максимального значения
              semval (зависит от реализации).

ВЕРСИИ

       semtimedop()  first appeared in Linux 2.5.52, and was subsequently backported  into  Linux
       2.4.22.  glibc support for semtimedop()  first appeared in Linux 2.3.3.

СТАНДАРТЫ

       POSIX.1-2001, POSIX.1-2008, SVr4.

ЗАМЕЧАНИЯ

       Структуры  процесса  sem_undo  не  наследуются потомками, созданными через fork(2), но они
       наследуются при выполнении системного вызова execve(2).

       Вызов semop() никогда  автоматически  не  перезапускается  после  прерывания  обработчиком
       сигнала, независимо от установки флага SA_RESTART при настройке обработчика сигнала.

       A semaphore adjustment (semadj)  value is a per-process, per-semaphore integer that is the
       negated sum of all operations performed on a semaphore specifying the SEM_UNDO flag.  Each
       process  has a list of semadj values—one value for each semaphore on which it has operated
       using SEM_UNDO.  When a process terminates, each of its  per-semaphore  semadj  values  is
       added to the corresponding semaphore, thus undoing the effect of that process's operations
       on the semaphore (but see BUGS below).  When a semaphore's value is directly set using the
       SETVAL  or  SETALL  request to semctl(2), the corresponding semadj values in all processes
       are cleared.  The clone(2)  CLONE_SYSVSEM flag allows more than one  process  to  share  a
       semadj list; see clone(2)  for details.

       Значения   semval,   sempid,   semzcnt   и   semnct  семафора  можно  получить  с  помощью
       соответствующих вызовов semctl(2).

   Ограничения семафоров
       Ниже приведены лимиты ресурсов наборов семафоров, влияющие на вызов semop():

       SEMOPM Максимальное количество операций, разрешённых для одного вызова semop(). До  версии
              Linux  3.19,  значение  по  умолчанию  было  3.  Начиная  с Linux 3.19, значение по
              умолчанию равно 500. В Linux это  ограничение  можно  прочитать  и  изменить  через
              третье  поле  /proc/sys/kernel/sem.  Замечание: это ограничение не должно превышать
              1000, так как есть риск, что  semop(2)  завершится  с  ошибкой  из-за  фрагментации
              памяти ядра при выделении памяти при копировании массива sops.

       SEMVMX Максимально допустимое значение semval: зависит от реализации (32767).

       Реализация  не  накладывает существенных ограничений на максимальное значение (SEMAEM), на
       которое можно изменить значение семафора при  выходе,  максимальное  количество  системных
       структур  откатываемых  операций  (SEMMNU)  и  максимальное  количество  элементов  отката
       системных параметров на процесс.

ДЕФЕКТЫ

       При завершении процесса его  набор  связанных  структур  semadj  используется  для  отката
       выполненных  действий  над  семафорами,  для  которых  был  установлен  флаг SEM_UNDO. Это
       повышает сложность: если одно (или более) этих изменений семафоров привело бы в результате
       к  попытке  уменьшить  значение  семафора ниже нуля, что должно быть сделано в реализации?
       Одним из возможных решений была бы блокировка до тех пор, пока не выполнятся все изменения
       семафоров.  Однако  это  нежелательно,  так  как это привело бы к блокированию процесса на
       неопределённый срок при его завершении. Другим вариантом является игнорирование сразу всех
       изменений  семафоров  (в  некоторой  степени,  аналогично  завершению с ошибкой, когда для
       операции с семафором указан IPC_NOWAIT). В Linux используется третий  вариант:  уменьшение
       значения  семафора до тех пор, пока это возможно ( т.е. до нуля) и разрешение немедленного
       завершения процесса.

       In Linux 2.6.x, x <= 10, there is a bug that in some circumstances prevents a thread  that
       is  waiting  for  a semaphore value to become zero from being woken up when the value does
       actually become zero.  This bug is fixed in Linux 2.6.11.

ПРИМЕРЫ

       В следующем фрагменте кода используется semop() для  атомарного  ожидания  момента,  когда
       значение  семафора  0  станет  равным  нулю и последующего увеличения значения семафора на
       единицу.

           struct sembuf sops[2];
           int semid;

           /* код для установки semid не показан */

           sops[0].sem_num = 0;        /* применяем к семафору 0 */
               sops[0].sem_op = 0;     /* ждём значения, равного 0 */
               sops[0].sem_flg = 0;

           sops[1].sem_num = 0;        /* применяем к семафору 0 */
               sops[1].sem_op = 1;     /* увеличиваем значение на 1 */
               sops[1].sem_flg = 0;

           if (semop(semid, sops, 2) == -1) {
               perror("semop");
               exit(EXIT_FAILURE);
           }

       A further example of the use of semop()  can be found in shmop(2).

СМ. ТАКЖЕ

       clone(2),   semctl(2),   semget(2),   sigaction(2),   capabilities(7),    sem_overview(7),
       sysvipc(7), time(7)

ПЕРЕВОД

       Русский    перевод    этой    страницы    руководства   был   сделан   Alexander   Golubev
       <fatzer2@gmail.com>,  Azamat  Hackimov  <azamat.hackimov@gmail.com>,   Hotellook,   Nikita
       <zxcvbnm3230@mail.ru>,       Spiros       Georgaras       <sng@hellug.gr>,       Vladislav
       <ivladislavefimov@gmail.com>,   Yuri   Kozlov   <yuray@komyakino.ru>   и    Иван    Павлов
       <pavia00@gmail.com>

       Этот  перевод  является  бесплатной  документацией;  прочитайте  Стандартную  общественную
       лицензию GNU версии 3 ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩ или более позднюю, чтобы
       узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.

       Если  вы  обнаружите  ошибки  в  переводе этой страницы руководства, пожалуйста, отправьте
       электронное письмо на ⟨man-pages-ru-talks@lists.sourceforge.net⟩.