Provided by: manpages-ru-dev_4.27.0-1_all bug

НАИМЕНОВАНИЕ

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

БИБЛИОТЕКА

       Стандартная библиотека языка C (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 (зависит от
              реализации).

СТАНДАРТЫ

       POSIX.1-2008.

ВЕРСИИ

       Linux 2.5.52 (backported into Linux 2.4.22), glibc 2.3.3.  POSIX.1-2001, 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;

           /* Code to set semid omitted */

           sops[0].sem_num = 0;        /* Operate on semaphore 0 */
           sops[0].sem_op = 0;         /* Wait for value to equal 0 */
           sops[0].sem_flg = 0;

           sops[1].sem_num = 0;        /* Operate on semaphore 0 */
           sops[1].sem_op = 1;         /* Increment value by one */
           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> и Kirill Rekhov <krekhov.dev@gmail.com>

       Этот перевод является свободной программной документацией; он распространяется на условиях  общедоступной
       лицензии  GNU  (GNU  General Public License - GPL, https://www.gnu.org/licenses/gpl-3.0.html версии 3 или
       более поздней) в отношении авторского права, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.

       Если вы обнаружите какие-либо ошибки в переводе этой страницы руководства, пожалуйста, сообщите  об  этом
       разработчику(ам)   по   его(их)  адресу(ам)  электронной  почты  или  по  адресу  списка рассылки русских
       переводчиков.

Справочные страницы Linux 6.9.1                   2 мая 2024 г.                                         semop(2)