Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
8 ферзей.doc
Скачиваний:
2
Добавлен:
01.04.2025
Размер:
309.76 Кб
Скачать

Взаимодействие процессов

Довольно часто процессам необходимо взаимодействовать с другими процессами. Например, в канале оболочки выходные данные одного процесса могут передаваться другому процессу, и так далее вниз по цепочке. Поэтому возникает необходимость во взаимодействии процессов, и желательно, по хорошо продуманной структуре без использования прерываний.

Будут рассмотрены три вопроса. Первый будет касаться уже упомянутого примера: как один процесс может передавать информацию другому процессу. Второй коснется обеспечения совместной работы процессов без создания взаимных помех, когда, к примеру, два процесса в системе бронирования авиабилетов одновременно пытаются захватить последнее место в самолете для разных клиентов. Третий вопрос коснется определения правильной последовательности на основе существующих взаимозависимостей: если процесс Л вырабатывает данные, а процесс Б их распечатывает, то процесс Б, перед тем как печатать, должен подождать, пока процесс Л не выработает определенные данные.

Следует отметить, что два из этих трех вопросов также применимы и к потокам.

Первый из них, касающийся передачи информации, применительно к потокам решается значительно легче, поскольку потоки имеют общее адресное пространство (взаимодействующие потоки, реализованные в различных адресных пространствах, подпадают под категорию взаимодействия процессов). А вот два других вопроса — относительно исключения взаимных помех и правильной последовательности — в полной мере применимы и к потокам: сходные проблемы и сходные методы их решения. Далее проблемы будут рассматриваться в контексте процессов, но нужно иметь в виду, что те же проблемы и решения применяются и в отношении потоков.

Состязательная ситуация

В некоторых операционных системах совместно работающие процессы могут использовать какое-нибудь общее хранилище данных, доступное каждому из них по чтению и по записи. Это общее хранилище может размещаться в оперативной памяти (возможно, в структуре данных ядра) или оно может быть представлено каким-нибудь общим файлом. Расположение общей памяти не меняет характер взаимодействия и возникающих при этом проблем. Чтобы посмотреть, как взаимодействие процессов осуществляется на практике, рассмотрим простой общеизвестный пример — спулер печати. Когда процессу необходимо распечатать какой-нибудь файл, он помещает имя этого файла в специальный каталог спулера.

Другой процесс под названием демон принтера периодически ведет проверку наличия файлов для печати, и в том случае, если такие файлы имеются, распечатывает их и удаляет их имена из каталога.

Представим, что в нашем каталоге спулера имеется большое количество областей памяти с номерами 0, 1, 2, ..., в каждой из которых может храниться имя файла. Также представим, что есть две общие переменные: out, указывающая на следующий файл, предназначенный для печати, и in, указывающая на следующую свободную область в каталоге. Эти две переменные могли бы неплохо сохраняться в файле, состоящем из двух слов и доступном всем процессам. В какой-то момент времени области от 0 до 3 пустуют (файлы уже распечатаны). Почти одновременно процессы А и Б решают, что им нужно поставить файл в очередь на печать. Эта ситуация показана на рис. 2.

Рис. 2. Состязательная ситуация, возникающая в спулере печати

В правовом пространстве, где применимы законы Мэрфи, может случиться следующее. Процесс А считывает значение переменной in и сохраняет значение 7 в локальной переменной по имени next_free_slot (следующая свободная область).

Сразу же после этого происходит прерывание по таймеру, центральный процессор решает, что процесс А проработал достаточно долго, и переключается на выполнение процесса Б. Процесс Б также считывает значение переменной in и также получает число 7. Он также сохраняет его в своей локальной переменной next_free_slot. К текущему моменту оба процесса полагают, что следующей доступной областью будет 7. Процесс Б продолжает выполняться. Он сохраняет имя своего файла в области 7 и присваивает переменной in обновленное значение 8. Затем он переходит к выполнению каких-нибудь других действий. Через некоторое время выполнение процесса Л возобновляется с того места, где он был остановлен. Он считывает значение переменной next_fгее_slot, видит там число 7 и записывает имя своего файла в область 7, затирая то имя файла, которое только что было в него помещено процессом Б. Затем он вычисляет next_ free_slot + 1, получает значение 8, и присваивает его переменной in. В каталоге спулера нет внутренних противоречий, поэтому демон печати не заметит никаких изъянов, но процесс Б никогда не получит вывода на печать. Пользователь Б будет годами бродить вокруг принтера, тоскливо надеясь получить распечатку, которой не будет никогда. Подобная ситуация, когда два или более процесса считывают или записывают какие-нибудь общие данные, а окончательный результат зависит от того, какой процесс и когда именно выполняется, называется состязательной ситуацией. Отладка программ, в которых присутствует состязательная ситуация, особой радости не доставляет. Результаты большинства прогонов могут быть вполне приемлемыми, но до поры до времени, пока не наступит тот самый редкий случай, когда произойдет нечто таинственное и необъяснимое.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]