48.2. Перепишите клиент-серверное приложение для обмена числовыми последовательностями из раздела 44.8, используя очереди POSIX-сообщений.
48.3. Напишите простую программу для обмена сообщениями (похожую на talk(1), но без интерфейса на основе curses), применяя очереди сообщений POSIX.
48.4. Измените программу из листинга 48.6 (mq_notify_sig.c) для демонстрации того, что оповещение о поступлении сообщений (подписка на которое оформляется с помощью вызова mq_notify()) приходит только один раз.
48.5. Замените обработчик сигнала в листинге 48.6 (mq_notify_sig.c) на вызов sigwaitinfo(). После получения структуры siginfo_t выведите ее содержимое на экран. Каким образом программа могла бы получить дескриптор очереди сообщений из этой структуры, возвращенной вызовом sigwaitinfo()?
48.6. Взгляните на листинг 48.7. Могли бы вы сделать buffer глобальной переменной и выделить для нее память лишь один раз в главной программе? Обоснуйте свой ответ.
49. Семафоры стандарта POSIX
Данная глава посвящена POSIX-семафорам, которые позволяют синхронизировать доступ к общим ресурсам между разными процессами и потоками выполнения. Предполагается, что читатель уже знаком с общей идеей семафоров и их назначением.
Стандартом SUSv3 предусмотрено два типа POSIX-семафоров.
•
•
POSIX-семафор представляет собой целое число, которое не может опускаться ниже нуля. Если процесс попытается сделать семафор отрицательным, то применяемый для этого вызов либо заблокируется, либо завершится ошибкой, сигнализирующей о недопустимости данной операции.
Ряд систем не предоставляет полной реализации POSIX-семафоров. Часто поддерживаются только анонимные семафоры, которые можно разделять между потоками. Именно так было в Linux 2.4; но с выходом ядра версии 2.6 и добавлением поддержки NPTL в glibc Linux поддерживает полную реализацию POSIX-семафоров.
В случае с Linux 2.6 и NPTL-потоками работа с семафорами (инкрементация и декрементация) реализована в виде системного вызова futex(2).
Для работы с именованными семафорами предусмотрены следующие функции:
• sem_open() — открывает или создает новый семафор, инициализирует его (если она его создала) и возвращает дескриптор, который можно использовать в дальнейшем;
• sem_post(sem) и sem_wait(sem) — соответственно инкрементируют и декрементируют значение семафора;
• sem_getvalue() — возвращает текущее значение семафора;
• sem_close() — закрывает семафор, ранее открытый вызывающим процессом;
• sem_unlink() — удаляет имя семафора и делает его кандидатом на удаление; само удаление произойдет, когда семафор закроет все процессы.
Стандарт SUSv3 не уточняет, как именно должно быть реализовано именование семафоров. В некоторых системах они представляют собой обычные файлы, хранящиеся в специальном каталоге в стандартной файловой системе. В Linux они имеют вид небольших объектов разделяемой памяти POSIX, хранящихся в файловой системе tmpfs (см. раздел 14.10), подключенной к каталогу /dev/shm, а их имена выглядят как sem.name. Данная файловая система обладает сохраняемостью на уровне ядра — объекты семафоров, хранящиеся в ней, существуют даже в том случае, если не открыты ни одним процессом, но теряются при выключении системы.
Именованные семафоры поддерживаются в ядре Linux, начиная с версии 2.6.
49.2.1. Открытие именованного семафора
Функция sem_open() открывает именованный семафор; если семафор не существует, он будет создан.
#include
#include
#include
sem_t *sem_open(const char *
/* mode_t
Возвращает указатель на семафор или SEM_FAILED, если произошла ошибка
Аргумент name обозначает имя семафора и подчиняется правилам, описанным в разделе 47.1.
Аргумент oflag представляет собой битовую маску, которая определяет, какая операция выполняется: открывается существующий семафор или создается новый. Если oflag равен 0, то мы обращаемся к существующему. В случае указания в маске oflag флага O_CREAT будет создан новый семафор (при условии, что имя name еще не занято). Если одновременно указать флаги O_CREAT и O_EXCL, а семафор с именем name уже существует, то вызов sem_open() завершится неудачей.