- •Часть 4. Локальное взаимодействие процессов
- •Глава 16. Блокирование записей 89
- •12.2. Процессы, потоки и общий доступ к информации
- •12.3. Живучесть объектов ipc
- •12.4. Пространства имен
- •12.5. Действие команд fork, exec и exit на объекты ipc
- •12.6. Комментарии к примерам ipc
- •12.7. Выводы по главе 12
- •12.8. Упражнения по главе 12
- •Глава 13. Именованные и неименованные каналы
- •13.1. Введение
- •13.2. Приложение типа клиент-сервер
- •13.3. Программные каналы
- •13.4. Функции popen и pclose
- •13.5. Именованные каналы (fifo)
- •13.6. Некоторые свойства именованных и неименованных каналов
- •13.7. Один сервер, несколько клиентов
- •13.8. Последовательные и параллельные серверы
- •13.9. Ограничения программных каналов и fifo
- •13.10. Выводы по главе 13
- •13.11. Упражнения по главе 13
- •Глава 14. Программные потоки
- •14.1. Введение
- •14.2. Концепция потоков
- •14.3. Идентификация потоков
- •14.4. Создание потока
- •14.5. Завершение потока
- •Функции управления процессами и потоками
- •14.6. Установка атрибутов потока
- •14.7. Реентерабельность
- •Альтернативные версии функций, безопасные в многопоточной среде
- •14.8. Локальные данные потоков
- •14.9. Принудительное завершение потоков
- •Некоторые точки выхода, определенные стандартом Posix.1
- •14.10. Потоки и сигналы
- •14.11. Выводы по главе 14
- •14.12. Упражнения по главе 14 Глава 15. Средства синхронизации потоков
- •15.1. Введение
- •15.2. Взаимные исключения: установка и снятие блокировки
- •15.2.1. Схема производитель-потребитель
- •15.2.2. Блокирование и опрос
- •15.2.3. Предотвращение тупиковых ситуаций
- •15.3. Условные переменные
- •15.3.1. Ожидание и сигнализация
- •15.3.2. Исключение состояния гонок
- •15.4. Блокировки чтения-записи
- •15.5. Атрибуты средств синхронизации потоков
- •15.5.1. Атрибуты взаимных исключений
- •Поведение взаимных исключений различных типов
- •15.5.2. Атрибуты условных переменных
- •15.5.3. Атрибуты блокировок чтения-записи
- •15.6. Выводы по главе 15
- •15.7. Упражнения по главе 15
- •Глава 16. Блокирование записей
- •16.1. Введение
- •16.2. Блокирование записей и файлов
- •16.3. Блокирование записей с помощью fcntl по стандарту Posix
- •16.4. Рекомендательная блокировка
- •16.5. Обязательная блокировка
- •16.6. Приоритет чтения и записи Выводы по главе 16
- •Упражнения по главе 16 Глава 17. System V ipc
- •17.1. Введение
- •17.2. Ключи типа key_t и функция ftok
- •17.3. Структура ipc_perm
- •17.4. Создание и открытие каналов ipc
- •17.5. Разрешения ipc
- •17.6. Программы ipcs и ipcrm
- •17.7. Ограничения ядра
- •17.8. Выводы по главе 17
- •17.9. Упражнения по главе 17
- •Глава 18. Очереди сообщений System V
- •18.1. Введение
- •18.2. Функция msgget
- •18.3. Функция msgsnd
- •18.4. Функция msgrcv
- •18.5. Функция msgctl
- •18.6. Пример программы клиент-сервер
- •18.7. Мультиплексирование сообщений
- •18.7.1. Пример: одна очередь на приложение
- •18.7.2. Пример: одна очередь для каждого клиента
- •18.8. Ограничения, накладываемые на очереди сообщений
- •18.9. Выводы по главе 18
- •18.10. Упражнения по главе 18
- •Глава 19. Семафоры System V
- •19.1. Введение
- •19.2. Функция semget
- •19.3. Функция semop
- •19.4. Функция semctl
- •19. . Ограничения семафоров System V
- •19. . Выводы по главе 19
- •19. . Упражнения по главе 19 Глава 20. Введение в разделяемую память
- •20.1. Введение
- •20.2. Функции mmap, munmap и msync
- •20.3. Увеличение счетчика в отображаемом в память файле
- •20.4. Неименованное отображение в память
- •20.5. Обращение к объектам, отображенным в память
- •20.6. Выводы по главе 20
- •20.7. Упражнения по главе 20
- •Глава 21. Разделяемая память System V
- •21.1. Введение
- •21.2. Функция shmget
- •21.3. Функция shmat
- •21.4. Функция shmdt
- •21.5. Функция shmctl
- •21.6. Ограничения, накладываемые на разделяемую память
- •21.7. Выводы по главе 21
- •21.8. Упражнения по главе 21
Часть 4. Локальное взаимодействие процессов
Глава 12. Обзор средств взаимодействия процессов Unix 2
12.1. Введение 2
12.2. Процессы, потоки и общий доступ к информации 4
12.3. Живучесть объектов IPC 5
12.4. Пространства имен 7
12.5. Действие команд fork, exec и exit на объекты IPC 8
12.6. Комментарии к примерам IPC 9
12.7. Выводы по главе 12 9
12.8. Упражнения по главе 12 10
Глава 13. Именованные и неименованные каналы 11
13.1. Введение 11
13.2. Приложение типа клиент-сервер 11
13.3. Программные каналы 11
13.4. Функции popen и pclose 18
13.5. Именованные каналы (FIFO) 20
13.6. Некоторые свойства именованных и неименованных каналов 25
13.7. Один сервер, несколько клиентов 28
13.8. Последовательные и параллельные серверы 35
13.9. Ограничения программных каналов и FIFO 36
13.10. Выводы по главе 13 36
13.11. Упражнения по главе 13 36
Глава 14. Программные потоки 38
14.1. Введение 38
14.2. Концепция потоков 38
14.3. Идентификация потоков 39
14.4. Создание потока 40
14.5. Завершение потока 42
14.6. Установка атрибутов потока 49
14.7. Реентерабельность 51
14.8. Локальные данные потоков 51
14.9. Принудительное завершение потоков 54
14.10. Потоки и сигналы 56
14.11. Выводы по главе 14 58
14.12. Упражнения по главе 14 58
Глава 15. Средства синхронизации потоков 59
15.1. Введение 59
15.2. Взаимные исключения: установка и снятие блокировки 62
15.2.1. Схема производитель-потребитель 64
15.2.2. Блокирование и опрос 68
15.2.3. Предотвращение тупиковых ситуаций 70
15.3. Условные переменные 71
15.3.1. Ожидание и сигнализация 72
15.3.2. Исключение состояния гонок 76
15.4. Блокировки чтения-записи 77
15.5. Атрибуты средств синхронизации потоков 83
15.5.1. Атрибуты взаимных исключений 84
15.5.2. Атрибуты условных переменных 86
15.5.3. Атрибуты блокировок чтения-записи 86
15.6. Выводы по главе 15 87
15.7. Упражнения по главе 15 88
Глава 16. Блокирование записей 89
16.1. Введение 89
16.2. Блокирование записей и файлов 89
16.3. Блокирование записей с помощью fcntl по стандарту Posix 90
16.4. Рекомендательная блокировка 91
16.5. Обязательная блокировка 92
16.6. Приоритет чтения и записи 92
Выводы по главе 16 92
Упражнения по главе 16 92
Глава 17. System V IPC 93
17.1. Введение 93
17.2. Ключи типа key_t и функция ftok 93
17.3. Структура ipc_perm 95
17.4. Создание и открытие каналов IPC 95
17.5. Разрешения IPC 98
17.6. Программы ipcs и ipcrm 99
17.7. Ограничения ядра 100
17.8. Выводы по главе 17 100
17.9. Упражнения по главе 17 100
Глава 18. Очереди сообщений System V 102
18.1. Введение 102
18.2. Функция msgget 103
18.3. Функция msgsnd 103
18.4. Функция msgrcv 105
18.5. Функция msgctl 106
18.6. Пример программы клиент-сервер 107
18.7. Мультиплексирование сообщений 111
18.7.1. Пример: одна очередь на приложение 112
18.7.2. Пример: одна очередь для каждого клиента 116
18.8. Ограничения, накладываемые на очереди сообщений 122
18.9. Выводы по главе 18 122
18.10. Упражнения по главе 18 123
Глава 19. Семафоры System V 124
19.1. Введение 124
19.2. Функция semget 129
19.3. Функция semop 131
19.4. Функция semctl 133
19. . Ограничения семафоров System V 134
19. . Выводы по главе 19 134
19. . Упражнения по главе 19 135
Глава 20. Введение в разделяемую память 136
20.1. Введение 136
20.2. Функции mmap, munmap и msync 140
20.3. Увеличение счетчика в отображаемом в память файле 143
20.4. Неименованное отображение в память 147
20.5. Обращение к объектам, отображенным в память 148
20.6. Выводы по главе 20 153
20.7. Упражнения по главе 20 154
Глава 21. Разделяемая память System V 155
21.1. Введение 155
21.2. Функция shmget 155
21.3. Функция shmat 156
21.4. Функция shmdt 156
21.5. Функция shmctl 156
21.6. Ограничения, накладываемые на разделяемую память 158
21.7. Выводы по главе 21 159
21.8. Упражнения по главе 21 159
Глава 12. Обзор средств взаимодействия процессов Unix
12.1. Введение
Большинство нетривиальных программ пишутся с использованием одной из форм межпроцессного взаимодействия (IPC – Interprocess Communication). Обычно под этим термином понимают передачу сообщений различных видов в какой-либо операционной системе. При этом могут использоваться различные формы синхронизации, требуемой современными видами взаимодействия, осуществляемыми, например, через разделяемую память. Это естественное следствие принципа разработки, заключающегося в том, что лучше создавать приложение, состоящее из отдельных взаимодействующих элементов, чем одну большую программу. Исторически разработка приложений пережила следующие этапы развития:
Сначала были большие цельные программы, которые делали все необходимое. Отдельные части программы реализовывались в виде функций, обменивавшихся информацией через аргументы, возвращаемые значения и глобальные переменные.
Потом стали создаваться небольшие программы, взаимодействующие друг с другом посредством различных средств IPC. Многие стандартные утилиты Unix были разработаны именно таким образом, причем для передачи информации использовались каналы интерпретатора.
Наконец, сейчас появилась возможность писать цельные программы, состоящие из взаимодействующих между собой потоков. В данном случае мы все равно применяем термин IPC, хотя процесс имеется только один.
Комбинация последних двух вариантов также возможна: несколько процессов, каждый из которых состоит из нескольких потоков, вполне могут взаимодействовать между собой.
Мы описываем возможность разделения решаемых задач между несколькими процессами или даже между потоками одного процесса. В мультипроцессорной системе такое приложение сможет выполняться гораздо быстрее, поэтому разделение задач между процессами способно повысить его быстродействие.
В этой части мы рассмотрим три формы IPC:
Передача сообщений (каналы, FIFO, очереди сообщений).
Синхронизация (взаимные исключения, условные переменные, блокировки чтения-записи, блокировка файлов, семафоры).
Разделяемая память (неименованная и именованная).
Нам могут возразить, что средства IPC, не предназначенные для взаимодействия по сети, вообще не следует использовать и что вместо этого следует изначально разрабатывать приложения с расчетом на использование в сети. Однако на практике средства IPC, работающие только в пределах одного узла, функционируют гораздо быстрее, чем сетевые, да и программы с их использованием оказываются проще. Разделяемая память и средства синхронизации обычно не могут использоваться по сети – они доступны только в пределах одного узла. Опыт и история показывают, что существует потребность в наличии как несетевых, так и сетевых форм IPC.
В процессе развития операционных систем семейства Unix за последние 40 лет методы передачи сообщений эволюционировали следующим образом:
каналы (pipes) были первой широко используемой формой взаимодействия процессов, доступной программам и пользователю (из интерпретатора команд). Основным недостатком каналов является невозможность их использования между процессами, не имеющими общего родителя (ancestor), но этот недостаток был устранен с появлением именованных каналов (named pipes), или каналов FIFO;
очереди сообщений стандарта System V (System V message queues) были добавлены к ядрам System V в начале 80-х. Они могут использоваться для передачи сообщений между процессами на одном узле вне зависимости от того, являются ли эти процессы родственными. Несмотря на сохранившийся префикс “System V”, большинство современных версий Unix, включая и те, которые не произошли от System V, поддерживают эти очереди.
Интересно также взглянуть на эволюцию различных форм синхронизации в процессе развития Unix:
самые первые программы, которым требовалась синхронизация (чаще всего для предотвращения одновременного изменения содержимого файла несколькими процессами), использовали для этого некоторые особенности файловой системы;
возможность блокирования записей (record locking) была добавлена к ядрам Unix в начале 80-х;
семафоры System V (System V semaphores) были добавлены вместе с возможностью совместного использования памяти (System V shared memory) и одновременно с очередями сообщений System V (начало 80-х). Эти IPC поддерживаются большинством современных версий Unix;
взаимные исключения, условные переменные и блокировки чтения-записи представляют собой три формы синхронизации, определенные стандартом Posix.1. Хотя обычно они используются для синхронизации совместной работы потоков внутри одного процесса, тем не менее, их можно применять и при организации взаимодействия процессов.
