Использование функций с семафорами в Linux |
![]() |
Добавил(а) microsin |
sem_wait, sem_timedwait, sem_trywait - эти функции используются для синхронизации между потоками путем блокировки на семафоре. Функции соответствуют стандарту POSIX.1-2001. #include < semaphore.h> Линковка должна происходить с -pthread. Макрос проверки требований для glibc (см. feature_test_macros(7)): sem_timedwait(): _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 [Описание] sem_wait() декрементирует (или блокирует выполнение вызвавшего потока) семафор, на который указывает sem. Если значение семафора больше нуля, то декремент выполняется, и функция выполнит немедленный возврат. Если значение семафора в настоящий момент равно 0, то функция блокирует выполнение до тех пор, пока не будет возможность выполнить декремент (т. е. пока значение семафора не станет больше 0), или пока обработчик сигнала (signal handler) не прервет вызов. sem_trywait() работает так же, как и sem_wait(), за исключением того, что если декремент не может быть произведен немедленно, то вместо блокировки вызов возвратит ошибку (errno установится в EAGAIN). sem_timedwait() также использует блокировку в случае невозможности декремента, как и sem_wait(), за исключением того, что abs_timeout задает предел интервала ожидания, в течение которого функция должна удерживать блокировку. Аргумент abs_timeout указывает на структуру timespec, которая задает абсолютную точку таймаута в секундах и наносекундах. Это время относительно Epoch, 1970-01-01 00:00:00 +0000 (UTC). Структура timespec определена следующим образом: struct timespec Если таймаут истек в течение вызова sem_timedwait(), и семафор не удалось немендленно заблокировать, то sem_timedwait() вызовет возврат по ошибке таймаута (будет возвращено значение -1, и errno установится в ETIMEDOUT). Если операция декремента может быть выполнена немедленно, то sem_timedwait() сделает возврат без ошибки (вернет 0), независимо от значения abs_timeout. Кроме того, для этого случая значение abs_timeout не проверяется. Возвращаемое значение: все эти 3 функции в случае успеха вернут 0. В случае ошибки значение семафора на выходе остается неизменным, будет возвращено -1, и переменная errno будет установлена для описания ошибки. EINTR. Вызов был прерван сигналом обработчика, см. signal(7). EINVAL. Параметр sem не указывает на допустимый семафор. Для sem_trywait() могут быть дополнительные значения errno: EAGAIN. Операция не может быть выполнена без блокировки (например у семафора в настоящий момент нулевое значение). Для sem_timedwait() могут быть дополнительные значения errno: EINVAL. Значение abs_timeout.tv_nsecs меньше 0, либо больше или равно 1000 миллионов. ETIMEDOUT. Время ожидания вызова истекло до блокировки семафора. Замечание: обработчик сигнала (signal handler) всегда обрывает блокировку на вызове этих функций, независимо от использования флага sigaction(2) SA_RESTART. [Пример использования] Ниже показан простой пример программы, демонстрирующий принцип работы на основе неименованого (unnamed) семафора. Программа принимает на входе 2 числовых аргумента. Первый аргумент задает значение в секундах, которое используется для взвода таймера alarm, чтобы сгенерировался сигнал SIGALRM. Этот обработчик выполнит sem_post(3), чтобы инкрементировать семафор, на котором производит ожидание функция sem_timedwait(), вызыванная в теле main(). Второй аргумент командной строки указывает длительность таймаута в секундах для sem_timedwait(). Следующие примеры запуска показывают, что происходит при указании различных начений аргументов для программы: $ ./testsem 2 3
About to call sem_timedwait()
sem_post() from handler
sem_timedwait() succeeded
$ ./testsem 2 1
About to call sem_timedwait()
sem_timedwait() timed out
Исходный код программы: // Пример использования семафора с таймаутом из статьи [1]. Makefile для компиляции: SRC := main.c all: →gcc $(CFLAGS_LINUX) -o testsem $(SRC) -lm $(INCLUDE) -L./lib -no-pie clean: →rm testsem -f Как компилировать: $ make clean
$ make
[Ссылки] 1. sem_timedwait(3) Linux man page site:linux.die.net. |