UNIX: взаимодействие процессов
Шрифт:
69-78 Здесь мы завершаем нашу работу, если либо не указан флаг O_CREAT, либо он указан, но семафор уже существует. В том и в другом случае мы открываем существующий семафор. Мы открываем файл вызовом open для чтения и записи, а затем отображаем его содержимое в адресное пространство процесса вызовом mmap.
ПРИМЕЧАНИЕ
Теперь легко понять, почему в Posix.1 сказано, что «обращение к копиям семафора приводит к неопределенным результатам». Если именованный семафор реализован через отображение файла в память, он отображается в адресное пространство всех процессов, в которых он открыт. Это осуществляется функцией sem_open для каждого процесса в отдельности. Изменения, сделанные одним процессом (например, изменение счетчика семафора), становятся доступны другим процессам через отображение в память. Если мы сделаем свою собственную копию структуры sem_t, она уже не будет общей для всех процессов. Хотя нам и может показаться, что вызовы срабатывают (функции для работы с семафором не будут возвращать ошибок, по крайней мере до вызова sem_close, которая не сможет отключить отображение для копии отображенного файла), с другими процессами мы при этом взаимодействовать не сможем. Однако заметьте (табл. 1.4), что области памяти с отображаемыми файлами передаются дочерним процессам при вызове fork, поэтому создание копии семафора ядром при порождении нового процесса проблем не вызовет.
79-96 Мы должны подождать, пока семафор не будет проинициализирован (если несколько потоков пытаются создать семафор приблизительно одновременно). Для этого мы вызываем stat и проверяем биты разрешений файла (поле st_mode структуры stat). Если бит user-execute снят, структура успешно проинициализирована.
97-108 При возникновении ошибки нужно аккуратно вернуть ее код.
Функция sem_close
В листинге 10.30 приведен текст нашей функции sem_close, которая просто вызывает munmap для отображенного в память файла. Если вызвавший процесс продолжит пользоваться указателем, который был ранее возвращен sem_open, он получит сигнал SIGSEGV.
Функция sem_unlink
Текст функции sem_unlink приведен в листинге 10.31. Она просто удаляет файл, через который реализован данный семафор, вызывая функцию unlink.
Функция sem_post
В листинге 10.32 приведен текст функции sem_post, которая увеличивает значение семафора, возобновляя выполнение всех процессов, заблокированных в ожидании этого события.
11-18 Прежде чем работать со структурой, нужно заблокировать соответствующее взаимное исключение. Если значение семафора изменяется с 0 на 1, нужно вызвать pthread_cond_signal, чтобы возобновилось выполнение одного из процессов, зарегистрированных на уведомление по данной условной переменной.
Функция sem_wait
В листинге 10.33 приведен текст функции sem_wait, которая ожидает изменения значения семафора с 0 на положительное, после чего уменьшает его на 1.