Уильям Стивенс UNIX: взаимодействие процессов МАСТЕР-КЛАСС Предисловие ЧАСТЬ 1 ВВЕДЕНИЕ В IPC UNIX ГЛАВА 1 Обзор средств взаимодействия процессов Unix 1.1. Введение 1.2. Процессы, потоки и общий доступ к информации Потоки 1.3. Живучесть объектов IPC 1.4. Пространства имен 1.5. Действие команд fork, exec и exit на объекты IPC 1.6. Обработка ошибок: функции-обертки Значение errno 1.7. Стандарты Unix Posix The Open Group Версии Unix и переносимость 1.8. Комментарий к примерам IPC 1.9. Резюме Упражнения ГЛАВА 2 Posix IPC 2.1. Введение 2.2. Имена IPC Функция px_ipc_name 2.3. Создание и открытие каналов IPC 2.4. Разрешения IPC 2.5. Резюме Упражнения ГЛАВА 3 System V IPC 3.1. Введение 3.2. Ключи типа key_t и функция ftok Пример 3.3. Структура ipc_perm 3.4. Создание и открытие каналов IPC 3.5. Разрешения IPC 3.6. Повторное использование идентификаторов 3.7. Программы ipcs и ipcrm 3.8. Ограничения ядра 3.9. Резюме Упражнения ЧАСТЬ 2 ОБМЕН СООБЩЕНИЯМИ ГЛАВА 4 Именованные и неименованные каналы 4.1. Введение 4.2. Приложение типа клиент-сервер 4.3. Программные каналы Пример 4.4. Двусторонние каналы 4.5. Функции popen и pclose Пример 4.6. Именованные каналы (FIFO) Пример Пример: неродственные клиент и сервер 4.7. Некоторые свойства именованных и неименованных каналов 4.8. Один сервер, несколько клиентов Открытие файла и отправка его в FIFO клиента Атомарность записи в FIFO FIFO и NFS 4.9. Последовательные и параллельные серверы Атака типа «отказ в обслуживании» 4.10. Потоки и сообщения 4.11. Ограничения программных каналов и FIFO 4.12. Резюме Упражнения ГЛАВА 5 Очереди сообщений Posix 5.1. Введение 5.2. Функции mq_open, mq_close, mq_unlink Пример: программа mqcreate1 Пример: программа mqunlink 5.3. Функции mq_getattr и mq_setattr Пример: программа mqgetattr Пример: программа mqcreate 5.4. Функции mqsend и mqreceive Пример: программа mqsend Пример: программа mqreceive 5.5. Ограничения очередей сообщений Пример: программа mqsysconf 5.6. Функция mq_notify Пример: простая программа с уведомлением Сигналы Posix: функции типа Async-Signal-Safe Пример: уведомление сигналом Пример: уведомление сигналом с отключением блокировки Пример: уведомление с использованием sigwait вместо обработчика Пример: очереди сообщений Posix и функция select Пример: запуск нового потока 5.7. Сигналы реального времени Posix Пример Функция signal_rt 5.8. Реализация с использованием отображения в память Функция mq_open Функция mq_close Функция mq_unlink Функция mq_getattr Функция mq_setattr Функция mq_notify Функция mq_send Функция mq_receive 5.9. Резюме Упражнения ГЛАВА 6 Очереди сообщений System V 6.1. Введениеы 6.2. Функция msgget 6.3. Функция msgsnd 6.4. Функция msgrcv 6.5. Функция msgctl Пример 6.6. Простые примеры Программа msgcreate Программа msgsnd Программа msgrcv Программа msgrmid Примеры Программа msgrcvid 6.7. Пример программы клиент-сервер 6.8. Мультиплексирование сообщений Пример: одна очередь на приложение Пример: одна очередь для каждого клиента 6.9. Использование select и poll с очередями сообщений 6.10. Ограничения, накладываемые на очереди сообщений Пример 6.11.Резюме Упражнения ЧАСТЬ 3 СИНХРОНИЗАЦИЯ ГЛАВА 7 Взаимные исключения и условные переменные 7.1. Введение 7.2. Взаимные исключения: установка и снятие блокировки 7.3. Схема производитель-потребитель 7.4. Блокировка и ожидание 7.5. Условные переменные: ожидание и сигнализация Исключение конфликтов блокировок 7.6. Условные переменные: время ожидания и широковещательная передача 7.7. Атрибуты взаимных исключений и условных переменных Завершение процесса, заблокировавшего ресурс 7.8. Резюме Упражнения ГЛАВА 8 Блокировки чтения-записи 8.1. Введение 8.2. Получение и сброс блокировки чтения-записи 8.3. Атрибуты блокировки чтения-записи 8.4. Реализация с использованием взаимных исключений и условных переменных Тип данных pthread_rwlock_t Функция pthread_rwlock_init Функция pthread_rwlock destroy Функция pthread_rwlock_rdlock Функция pthread_rwlock_tryrdlock Функция pthread_rwlock_wrlock Функция pthread_rwlock_trywrlock Функция pthread_rwlock_unlock 8.5. Отмена выполнения потоков Пример 8.6. Резюме Упражнения ГЛАВА 9 Блокирование записей 9.1. Введение 9.2. Блокирование записей и файлов История 9.3. Блокирование записей с помощью fcntl по стандарту Posix Пример Пример: упрощение с помощью макросов 9.4. Рекомендательная блокировка Пример: несотрудничающие процессы 9.5. Обязательная блокировка Пример 9.6. Приоритет чтения и записи Пример: блокировка на чтение при наличии в очереди блокировки на запись Пример: имеют ли приоритет запросы на запись перед запросами на чтение? 9.7. Запуск единственного экземпляра демона 9.8. Блокирование файлов 9.9. Блокирование в NFS 9.10. Резюме Упражнения ГЛАВА 10 Семафоры Posix 10.1.Введение 10.2. Функции sem_open, sem_close и sem_unlink 10.3. Функции sem_wait и sem_trywait 10.4. Функции sem_post и sem_getvalue 10.5. Простые примеры Программа semcreate Программа semunlink Программа semgetvalue Программа semwait Программа sempost Примеры 10.6. Задача производителей и потребителей Зависание 10.7. Блокирование файлов 10.8. Функции sem_init и sem_destroy Пример 10.9. Несколько производителей, один потребитель 10.10. Несколько производителей, несколько потребителей 10.11. Несколько буферов 10.12. Использование семафоров несколькими процессами 10.13. Ограничения на семафоры Пример: программа semsysconf 10.14. Реализация с использованием FIFO Функция sem_open Функция sem_close Функция sem_unlink Функция sem_post Функция sem_wait 10.15. Реализация с помощью отображения в память Функция sem_open Функция sem_close Функция sem_unlink Функция sem_post Функция sem_wait Функция sem_trywait Функция sem_getvalue 10.16. Реализация с использованием семафоров System V Функция sem_open Функция sem_close Функция sem_unlink Функция sem_post Функция sem_wait Функция sem_trywait Функция sem_getvalue 10.17. Резюме Упражнения ГЛАВА 11 Семафоры System V 11.1.Введение 11.2. Функция semget Инициализация значения семафора 11.3. Функция semop 11.4. Функция semctl 11.5. Простые программы Программа semcreate Программа semrmid Программа semsetvalues Программа semgetvalues Программа semops Примеры 11.6. Блокирование файлов 11.7. Ограничения семафоров System V Пример 11.8. Резюме Упражнения ЧАСТЬ 4 РАЗДЕЛЯЕМАЯ ПАМЯТЬ ГЛАВА 12 Введение в разделяемую память 12.1. Введение 12.2. Функции mmap, munmap и msync Почему вообще используется отображение в память? 12.3. Увеличение счетчика в отображаемом в память файле 12.4. Неименованное отображение в память в 4.4BSD 12.5. Отображение в память в SVR4 с помощью /dev/zero 12.6. Обращение к объектам, отображенным в память 12.7. Резюме Упражнения ГЛАВА 13 Разделяемая память Posix 13.1. Введение 13.2. Функции shm_open и shm_unlink 13.3. Функции ftruncate и fstat 13.4. Простые программы Программа shmcreate Программа shmunlink Программа shmwrite Программа shmread Примеры Пример 13.5. Увеличение общего счетчика 13.6. Отправка сообщений на сервер 13.7. Резюме Упражнения ГЛАВА 14 Разделяемая память System V 14.1. Введение 14.2. Функция shmget 14.3. Функция shmat 14.4. Функция shmdt 14.5. Функция shmctl 14.6. Простые программы Программа shmget Программа shmrmid Программа shmwrite Программа shmread Примеры 14.7. Ограничения, накладываемые на разделяемую память Пример 14.8. Резюме Упражнение ЧАСТЬ 5 УДАЛЕННЫЙ ВЫЗОВ ПРОЦЕДУР ГЛАВА 15 Двери 15.1. Введение Пример 15.2. Функция door_call 15.3. Функция door_create 15.4. Функция door_return 15.5. Функция door_cred 15.6. Функция door_info 15.7. Примеры Функция door_info Буфер результатов слишком мал Функция door_cred и информация о клиенте Автоматическое управление потоками сервера Автоматическое управление потоками сервера: несколько процедур Атрибут DOOR_UNREF для серверов 15.8. Передача дескрипторов Пример 15.9. Функция door server_create 15.10. Функции door_bind, door unbind и door_revoke 15.11. Досрочное завершение клиента или сервера Досрочное завершение сервера Непрерываемость системного вызова door_call Идемпотентные и неидемпотентные процедуры Досрочное завершение клиента 15.12. Резюме Упражнения ГЛАВА 16 Пакет Sun RPC 16.1. Введение Пример История 16.2. Многопоточность 16.3. Привязка сервера Inetd и серверы RPC 16.4. Аутентификация 16.5. Тайм-аут и повторная передача Управление соединением по TCP Идентификатор транзакций Кэш повторных ответов 16.6. Семантика вызовов 16.7. Досрочное завершение сервера или клиента Досрочное завершение сервера Досрочное завершение клиента 16.8. XDR: представление внешних данных Пример: использование XDR без RPC Пример: вычисление размера буфера Пример: необязательные данные Пример: обработка связного списка 16.9. Форматы пакетов RPC 16.10. Резюме Упражнения Эпилог ПРИЛОЖЕНИЕ А Измерение производительности А.1. Введение А.2. Результаты Результаты измерения полосы пропускания сообщений Результаты измерения задержки Результаты синхронизации потоков Результаты синхронизации процессов А.З. Измерение полосы пропускания: программы Измерение полосы пропускания канала Измерение полосы пропускания очереди сообщений Posix Программа измерения полосы пропускания очереди System V Программа измерения полосы пропускания дверей Программа определения полосы пропускания Sun RPC А.4. Измерение задержки передачи сообщений: программы Программа измерения задержки канала Программа измерения задержки очередей сообщений Posix Измерение задержки очередей сообщений System V Программа измерения задержки интерфейса дверей Программа измерения времени задержки Sun RPC А.5. Синхронизация потоков: программы Взаимные исключения Posix Блокировки чтения-записи Семафоры Posix, размещаемые в памяти Именованные семафоры Posix Семафоры System V Блокировка записей fcntl А.6. Синхронизация процессов: программы Взаимные исключения Posix между процессами ПРИЛОЖЕНИЕ Б Основы многопоточного программирования Б.1. Введение Б.2. Основные функции для работы с потоками: создание и завершение ПРИЛОЖЕНИЕ В Вспомогательные исходные коды В.1. Заголовочный файл unpipc.h B.2. Заголовочный файл config.h В.З. Стандартные функции вывода сообщений об ошибках ПРИЛОЖЕНИЕ Г Решения некоторых упражнений Глава 1 Глава 2 Глава 3 Глава 4 Глава 5 Глава 6 Глава 7 Глава 9 Глава 10 Глава 11 Глава 12 Глава 13 Глава 14 Глава 15 Глава 16 Литература
1.2. Процессы, потоки и общий доступ к информации В традиционной модели программирования Unix в системе могут одновременно выполняться несколько процессов, каждому из которых выделяется собственное адресное пространство. Это иллюстрирует рис. 1.1.
Рис. 1.1. Совместное использование информации процессами
1. Два процесса в левой части совместно используют информацию, хранящуюся в одном из объектов файловой системы. Для доступа к этим данным каждый процесс должен обратиться к ядру (используя функции read, write, lseek, write, lseek и аналогичные). Некоторая форма синхронизации требуется при изменении файла, для исключения помех при одновременной записи в файл несколькими процессами и для защиты процессов, читающих из файла, от тех, которые пишут в него.
2. Два процесса в середине рисунка совместно используют информацию, хранящуюся в ядре. Примерами в данном случае являются канал, очередь сообщений или семафор System V. Для доступа к совместно используемой информации в этом случае будут использоваться системные вызовы.
3. Два процесса в правой части используют общую область памяти, к которой может обращаться каждый из процессов. После того как будет получен доступ к этой области памяти, процессы смогут обращаться к данным вообще без помощи ядра. В этом случае, как и в первом, процессам, использующим общую память, также требуется синхронизация.
Обратите внимание, что ни в одном из этих случаев количество взаимодействующих процессов не ограничивается двумя. Любой из описанных методов работает для произвольного числа взаимодействующих процессов. На рисунке мы изображаем только два для простоты.