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

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

       sem_wait, sem_timedwait, sem_trywait - блокирует семафор

БИБЛИОТЕКА

       Библиотека потоков POSIX (libpthread, -lpthread)

ОБЗОР

       #include <semaphore.h>

       int sem_wait(sem_t *sem);
       int sem_trywait(sem_t *sem);
       int sem_timedwait(sem_t *restrict sem,
                         const struct timespec *restrict abs_timeout);

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

       sem_timedwait():
           _POSIX_C_SOURCE >= 200112L

ОПИСАНИЕ

       Функция  sem_wait() уменьшает (блокирует) семафор, на который указывает sem. Если значение семафор больше
       нуля, то выполняется уменьшение и функция сразу завершается. Если значение семафора равно нулю, то  вызов
       блокируется до тех пор, пока не станет возможным выполнить уменьшение (т. е., значение семафора не станет
       больше нуля), или пока не вызовется обработчик сигнала.

       Функция  sem_trywait()  подобна  sem_wait(),  за  исключением  того, что если уменьшение нельзя выполнить
       сразу, то вызов завершается с ошибкой (errno становится равным EAGAIN), а не блокируется.

       sem_timedwait()  is the same as sem_wait(), except that abs_timeout specifies a limit on  the  amount  of
       time  that  the  call  should  block  if  the decrement cannot be immediately performed.  The abs_timeout
       argument points to a timespec(3)  structure that specifies an absolute timeout in seconds and nanoseconds
       since the Epoch, 1970-01-01 00:00:00 +0000 (UTC).

       Если на момент вызова время ожидания уже истекло и семафор нельзя заблокировать сразу, то sem_timedwait()
       завершается с ошибкой просрочки (errno становится равным ETIMEDOUT).

       Если операцию можно выполнить сразу, то  sem_timedwait()  никогда  не  завершится  с  ошибкой  просрочки,
       независимо от значения abs_timeout. Кроме того, в этом случае не проверяется корректность abs_timeout.

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

       При  успешном  выполнении  все  функции  возвращают  0;  при  ошибке  значение  семафора  не  изменяется,
       возвращается -1, а в errno указывается причина ошибки.

ОШИБКИ

       EAGAIN (sem_trywait())  The operation could not  be  performed  without  blocking  (i.e.,  the  semaphore
              currently has the value zero).

       EINTR  Вызов был прерван обработчиком сигнала; смотрите signal(7).

       EINVAL Значение sem не является корректным для семафора.

       EINVAL (sem_timedwait())   The  value of abs_timeout.tv_nsecs is less than 0, or greater than or equal to
              1000 million.

       ETIMEDOUT
              (sem_timedwait())  The call timed out before the semaphore could be locked.

АТРИБУТЫ

       Описание терминов данного раздела смотрите в attributes(7).
       ┌─────────────────────────────────────────────────────────────────────┬──────────────────────┬──────────┐
       │ ИнтерфейсАтрибутЗначение │
       ├─────────────────────────────────────────────────────────────────────┼──────────────────────┼──────────┤
       │ sem_wait(), sem_trywait(), sem_timedwait()                          │ Безвредность в нитях │ MT-Safe  │
       └─────────────────────────────────────────────────────────────────────┴──────────────────────┴──────────┘

СТАНДАРТЫ

       POSIX.1-2008.

ИСТОРИЯ

       POSIX.1-2001.

ПРИМЕРЫ

       Программа (несколько упрощённая), показанная ниже, работает  с  безымянным  семафором.  Она  ожидает  два
       аргумента  командной  строки.  В  первом  аргументе  задаётся значение в секундах, которое используется в
       будильнике для генерации сигнала SIGALRM. Этот обработчик выполняет sem_post(3) для увеличения  семафора,
       которого ждёт в main() вызов sem_timedwait(). Во втором аргументе задаётся период ожидания в секундах для
       sem_timedwait(). Далее показано что происходит в двух разных запусках программы:

           $ ./a.out 2 3
           About to call sem_timedwait()
           sem_post() из обработчика
           sem_timedwait() выполнена успешно
           $ ./a.out 2 1
           About to call sem_timedwait()
           истекло время ожидания sem_timedwait()

   Исходный код программы

       #include <errno.h>
       #include <semaphore.h>
       #include <signal.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <time.h>
       #include <unistd.h>

       #include <assert.h>

       sem_t sem;

       #define handle_error(msg) \
           do { perror(msg); exit(EXIT_FAILURE); } while (0)

       static void
       handler(int sig)
       {
           write(STDOUT_FILENO, "sem_post() from handler\n", 24);
           if (sem_post(&sem) == -1) {
               write(STDERR_FILENO, "sem_post() failed\n", 18);
               _exit(EXIT_FAILURE);
           }
       }

       int
       main(int argc, char *argv[])
       {
           struct sigaction sa;
           struct timespec ts;
           int s;

           if (argc != 3) {
               fprintf(stderr, "Usage: %s <alarm-secs> <wait-secs>\n",
                       argv[0]);
               exit(EXIT_FAILURE);
           }

           if (sem_init(&sem, 0, 0) == -1)
               handle_error("sem_init");

           /* Establish SIGALRM handler; set alarm timer using argv[1]. */

           sa.sa_handler = handler;
           sigemptyset(&sa.sa_mask);
           sa.sa_flags = 0;
           if (sigaction(SIGALRM, &sa, NULL) == -1)
               handle_error("sigaction");

           alarm(atoi(argv[1]));

           /* Calculate relative interval as current time plus
              number of seconds given argv[2]. */

           if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
               handle_error("clock_gettime");

           ts.tv_sec += atoi(argv[2]);

           printf("%s() about to call sem_timedwait()\n", __func__);
           while ((s = sem_timedwait(&sem, &ts)) == -1 && errno == EINTR)
               continue;       /* Restart if interrupted by handler. */

           /* Check what happened. */

           if (s == -1) {
               if (errno == ETIMEDOUT)
                   printf("sem_timedwait() timed out\n");
               else
                   perror("sem_timedwait");
           } else
               printf("sem_timedwait() succeeded\n");

           exit((s == 0) ? EXIT_SUCCESS : EXIT_FAILURE);
       }

СМОТРИТЕ ТАКЖЕ

       clock_gettime(2), sem_getvalue(3), sem_post(3), timespec(3), sem_overview(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                  15 июня 2024 г.                                     sem_wait(3)