Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Примеры отношений между процессами
Чтобы посмотреть, как взаимодействие процессов осуществляется на практике, давайте рассмотрим простой общеизвестный пример – спулер печати. Когда процессу необходимо распечатать какой-нибудь файл, он помещает имя этого файла в специальный каталог спулера. Другой процесс под названием демон принтера периодически ведет проверку наличия файлов для печати, и в том случае, если такие файлы имеются, распечатывает их и удаляет их имена из каталога. [2, С. 151] Здесь выполняется типичный случай отношения параллелизма. Однако здесь возникает ситуация взаимонеобходимости: нет смысла в существовании процесса-демона принтера без процесса-спулера, в то же время нет смысла в существовании спулера без демона, т. е. данные процессы должны существовать в системе одновременно, при этом должны быть обеспечены способы их межпроцессного взаимодействия. Отношение следования выражается в том, что процессы, которые ставят на печать свои файлы не могут этого делать без существования процесса-спулера, т. е. они должны реализовываться позже. Отношение альтернативы выражается в следующем: нет смысла в существовании двух процессов-демонов печати. В данном случае существование одного исключает существование другого. В противном случае могла бы возникнуть ситуация, когда оба процесса-демона вывели бы на печать один и тот же документ несколько раз. А теперь рассмотрим самое интересное отношение – отношение конкуренции. Оно возникает, когда несколько процессов должны получить доступ к одному и тому же ресурсу. Представьте, что в нашем каталоге спулера имеется большое количество областей памяти с номерами 0, 1, 2,..., в каждой из которых может храниться имя файла. Также представьте, что есть две общие переменные: out, указывающая на следующий файл, предназначенный для печати, и in, указывающая на следующую свободную область в каталоге. Эти две переменные могли бы неплохо сохраняться в файле, состоящем из двух слов и доступном всем процессам. В какой-то момент времени области от 0 до 3 пустуют (файлы уже распечатаны). Почти одновременно процессы А и Б решают, что им нужно поставить файл в очередь на печать. Эта ситуация показана на рисунке 1. [2, С. 151] Рисунок 1 – Одновременное стремление двух процессов получить доступ к общей памяти В соответствии с законом Мерфи (который звучит примерно так: «Если что-то плохое может случиться, оно непременно случится», иностранный аналог русского «закона подлости»), возможна следующая ситуация: · Процесс А считывает значение (7) переменной in и сохраняет его в локальной переменной next_free_slot. После этого происходит прерывание по таймеру, и процессор переключается на процесс Б. · Процесс Б, в свою очередь, считывает значение переменной in (опять 7) и сохраняет его в своей локальной переменной next_free_slot. В данный момент оба процесса считают, что следующий свободный сегмент – седьмой. Процесс Б сохраняет в каталоге спулера имя файла и заменяет значение in на 8, затем продолжает заниматься своими задачами, не связанными с печатью. · Наконец, управление переходит к процессу А, и он продолжает с того места, на котором остановился. Он обращается к переменной next_free_slot, считывает ее значение и записывает в сегмент 7 имя файла (разумеется, удаляя при этом имя файла, помещенное туда процессом В). Затем он заменяет значение in на 8 (next_free_slot+1=8). Структура каталога спулера не нарушена, поэтому демон печати не заподозрит ничего плохого, но файл процесса В не будет напечатан. [3, С. 93-94] Пользователь Б будет годами бродить вокруг принтера, тоскливо надеясь получить распечатку, которой не будет никогда. Подобная ситуация, когда два или более процесса считывают или записывают какие-нибудь общие данные, а окончательный результат зависит от того, какой процесс и когда именно выполняется, называется состязательной ситуацией (гонками). Ключом к предупреждению проблемы в этой и во многих других ситуациях использования общей памяти, общих файлов и вообще чего-нибудь общего может послужить определение способа, при котором в каждый конкретный момент времени доступ к общим данным по чтению и записи может получить только один процесс. Иными словами, нам нужен способ взаимного исключения. Выбор подходящих элементарных операций для достижения взаимного исключения является основным вопросом конструирования любой операционной системы. Проблемы обхода состязательных ситуаций могут быть также сформулированы в абстрактной форме. Какую-то часть времени процесс занят внутренними вычислениями и чем-нибудь другим, не создающим состязательных ситуаций. Но иногда процесс вынужден обращаться к общей памяти или файлам либо совершать какие- нибудь другие значимые действия, приводящие к состязаниям. Та часть программы, в которой используется доступ к общей памяти, называется критической областью или критической секцией (см. рисунок 2). Если бы удалось все выстроить таким образом, чтобы никакие два процесса не находились одновременно в своих критических областях, это позволило бы избежать состязаний. Хотя выполнение этого требования позволяет избежать состязательных ситуаций, его недостаточно для того, чтобы параллельные процессы правильно выстраивали свою совместную работу и эффективно использовали общие данные. Для приемлемого решения необходимо соблюдение четырех условий: 1. Два процесса не могут одновременно находиться в своих критических областях. 2. Не должны выстраиваться никакие предположения по поводу скорости или количества центральных процессоров. 3. Никакие процессы, выполняемые за пределами своих критических областей, не могут блокироваться другими процессами. 4. Процессы не должны находиться в вечном ожидании входа в свои критические области. [2, С. 152-153] Рисунок 2 – Взаимное исключение использования критических областей Чем опасны состязательные ситуации можно увидеть на примере рентгеновского аппарата лучевой терапии «Therac-25». Аппарат лучевой терапии «Therac-25» был медицинским аппаратом, в котором вопросы безопасности были возложены исключительно на программное обеспечение. Этот аппарат работал в трёх режимах: 1) электронная терапия: электронная пушка напрямую облучала пациента; компьютер задавал энергию электронов от 5 до 25 МэВ; 2) рентгеновская терапия: электронная пушка облучала вольфрамовую мишень, и пациент облучался рентгеновскими лучами, проходившими через конусообразный рассеиватель; в этом режиме энергия электронов была 25 МэВ; 3) в третьем режиме никакого излучения не было: на пути электронов (на случай аварии) располагался стальной отражатель, а излучение имитировалось светом; этот режим применялся для того, чтобы точно навести пучок на больное место. Эти три режима задавались вращающимся диском, в котором было отверстие с отклоняющими магнитами для электронной терапии, и мишень с рассеивателем для рентгеновской. Из-за состояния гонки между управляющей программой и обработчиком клавиатуры иногда случалось, что в режиме рентгеновской терапии диск оказывался в положении «Электронная терапия», и пациент напрямую облучался пучком электронов в 25 МэВ, что вело к переоблучению. При этом датчики выводили «Нулевая доза», поэтому оператор мог повторить процедуру, усугубляя ситуацию. В результате погибло несколько пациентов. [4]
|