
- •Министерство образования и науки Российской Федерации
- •Цель лекции
- •План лекции
- •1 Происхождение вычислительных машин
- •2 Изучение алгоритмов
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Биты и их хранение
- •2 Оперативная память
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Устройства внешней памяти
- •3 Хранение и поиск файлов
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Представление числовых значений
- •2 Хранение целых чисел
- •3 Хранение дробей
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Представление текста
- •2 Представление изображений
- •Достоинства пиксельной графики
- •Недостатки пиксельной графики
- •Достоинства векторной графики
- •Недостатки векторной графики
- •3 Представление звука
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Сжатие изображений
- •2 Ошибки передачи данных
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Архитектура эвм
- •2 Связь процессора с другими устройствами
- •3 Другие архитектуры
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Машинный язык
- •2 Пример машинного языка
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Выполнение программы
- •2 Пример выполнения программы
- •3 Программы и данные
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Логические операции
- •2 Операции сдвига
- •3 Арифметические операции
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Эволюция операционных систем
- •2 Архитектура операционных систем
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Понятие процесса
- •2 Управление процессами
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Классификация сетей
- •2 Сетевые протоколы*
- •3 Безопасность сетей
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Понятие алгоритма
- •2 Представление алгоритма
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Теория решения задач
- •2 Общие методы решения задач
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Алгоритм последовательного поиска
- •2 Управление циклами
- •3 Алгоритм сортировки методом вставки
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Алгоритмы поиска и сортировки
- •2 Управление рекурсией
- •3 Разработка рекурсивных процедур
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Эффективность алгоритмов
- •2 Верификация программ
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Эволюция и классификация языков программирования
- •2 Концепции традиционного программирования
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Процедурные единицы
- •2 Реализация языка программирования
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Объектно-ориентированное программирование
- •2 Декларативное программирование
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Структуры данных
- •Integer Scores (2.9).
- •2 Статические и динамические структуры
- •3 Указатели
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Массивы
- •2 Списки
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Структура и функции стека
- •2 Реализация стека
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Очереди
- •2 Деревья
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Пользовательские типы данных
- •Int Age;
- •2 Классы
- •Int *StackEntries;
- •3 Стандартная библиотека шаблонов
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Роль операционной системы
- •2 Последовательные файлы
- •3 Вопросы программирования
- •0000000010000110
- •001100010011001100110100
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Основные положения индексации
- •2 Вопросы программирования
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Основные положения хеширования
- •2 Вопросы программирования
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Общие вопросы
- •2 Система управления базой данных
- •3 Поддержка целостности баз данных
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Модели баз данных
- •2 Реляционная модель баз данных
- •3 Объектно-ориентированные базы данных
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Интеллект и машины
- •2 Распознавание образов
- •3 Мышление
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Искусственные нейронные сети
- •2 Генетические алгоритмы
- •Контрольные вопросы
- •Невычислимые функции Цель лекции
- •План лекции
- •1 Основы машины Тьюринга
- •2 Невычислимая функция
- •3 Сложность задач
- •Листинг 1. Процедура MergeLists для объединения двух упорядоченных списков
- •Листинг 2. Алгоритм сортировки слиянием, реализованный в процедуре MergeSort
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Шифрование с открытым ключом
- •2 Модульная арифметика
- •Контрольные вопросы
- •Литература
- •Internet-ресурсы
2 Управление процессами
Задачи, связанные с координацией процессов, решаются планировщиком и диспетчером, входящими в состав ядра операционной системы. Планировщик ведет пул записей о процессах, присутствующих в вычислительной системе, вводит в него сведения о новых процессах и удаляет информацию о завершившихся. Для отслеживания состояния всех процессов Планировщик организует в основной памяти блок информации, называемый таблицей процессов (process table). Каждый раз, когда машине дается новое задание, планировщик создает процесс для этого задания посредством занесения новой записи в таблицу процессов. Эта запись содержит сведения об объеме выделенной процессу памяти (эта информация поступает от модуля управления памятью), о присвоенном ему приоритете, а также о том, находится процесс в состоянии готовности или ожидания. Процесс находится в состоянии готовности (ready), если его развитие может продолжаться, и переводится в состояние ожидания (waiting), когда его развитие приостанавливается до тех пор, пока не произойдут некоторые внешние события, например, завершится процедура доступа к диску или поступит сообщение от другого процесса.
Диспетчер — это компонент ядра, отвечающий за то, чтобы запланированные процессы действительно выполнялись. В системе с разделением времени эта задача решается посредством разбиения времени процессора на короткие интервалы, называемые квантами (обычно продолжительностью около 50 миллисекунд). По истечении этого времени происходит принудительное переключение центрального процессора от одного процесса к другому; так что каждому процессу предоставляется возможность непрерывного выполнения лишь в течение одного кванта времени (рис. 1). Процедура смены одного процесса другим называется переключением процессов (process switch).
Каждый раз, когда процессу предоставляется очередной квант времени, диспетчер инициирует цепь таймера, подготавливая его к измерению продолжительности следующего кванта. По окончании установленного кванта цепь таймера генерирует сигнал, называемый прерыванием (interrupt). Центральный процессор реагирует на этот сигнал так же, как и человек, которого останавливают во время выполнения определенного задания. Человек прекращает свою работу, записывает текущее состояние задачи и обращает внимание на то, что его отвлекло. При получении сигнала прерывания центральный процессор завершает текущий машинный цикл, сохраняет свое положение в текущем процессе (подробнее мы обсудим это чуть ниже) и начинает выполнять программу, называемую обработчиком прерываний (interrupt handler), помещенную в заранее определенное место в основной памяти.
В нашем сценарии разделения времени обработчик прерываний — это часть диспетчера. Таким образом, результатом поступления сигнала прерывания является приостановка текущего процесса и передача управления диспетчеру. В этот момент диспетчер разрешает планировщику обновить состояние таблицы процессов (например, возможно, что приоритет только что отработавшего свой квант времени процесса следует понизить, а приоритеты других процессов — повысить). Затем из таблицы процессов диспетчер выбирает процесс с наивысшим приоритетом из числа процессов, находящихся в состоянии готовности, заново инициализирует цепь таймера, после чего разрешает выбранному процессу использовать новый квант времени.
Рисунок 1 - Разделение времени между процессами А и В
Главным условием успешной работы системы с разделением времени является ее способность остановить, а затем повторно запустить процесс. Если вас прерывают во время чтения книги, то возможность продолжить чтение позднее зависит от вашей способности вспомнить, на чем вы остановились и что прочли до этого момента. Короче говоря, вы должны иметь возможность воссоздать ситуацию такой, какой она была непосредственно в момент прерывания. В отношении процесса эта ситуация есть его состояние. Напомним, что состояние процесса включает в себя значение счетчика адреса, а также содержимое регистров ЦП и ячеек памяти, к которым выполняется обращение. Машины, разработанные для систем с разделением времени, включают средства, позволяющие сохранять эту информацию как реакцию центрального процессора на сигнал прерывания. Кроме того, машинный язык таких процессоров обычно включает специальные команды для перезагрузки ранее сохраненной информации о состоянии. Подобные функциональные возможности вычислительных машин упрощают задачу диспетчера по переключению процессов и служат примером того, как потребности современных операционных систем оказывают влияние на разработку компьютеров.
Иногда использование процессом предоставленного ему кванта времени заканчивается раньше, чем истекает интервал, установленный на таймере. Например, если процесс выдает запрос на выполнение операции ввода/вывода, скажем запрос на получение данных с диска, выделенный процессу квант времени будет принудительно завершен, так как в противном случае процесс бесполезно потратит оставшееся время на ожидание, когда контроллер выполнит запрос. В этом случае планировщик обновит таблицу процессов, отразив в ней переход данного процесса в состояние ожидания, а диспетчер предоставит очередной квант времени процессу, находящемуся в состоянии готовности. Позднее (возможно, через несколько сотен миллисекунд), когда контроллер сообщит о том, что поступивший запрос на операцию ввода/вывода уже выполнен, планировщик вновь отметит данный процесс, как готовый к выполнению, и этот процесс сможет конкурировать за получение очередного кванта времени ЦП.
Различные составляющие операционной системы обычно выполняются как отдельные процессы, конкурирующие в системе с разделением времени за получение от диспетчера квантов времени ЦП. Для координации своих действий этим процессам необходимо взаимодействовать друг с другом. Например, чтоб запланировать новый процесс, планировщик должен получить для него место памяти от программы управления памятью, а чтобы получить доступ к файлу, массовой памяти, любой процесс должен сначала получить информацию об это файле от программы управления файлами.
Обмен сообщениями между процессами называется межпроцессорным взаимодействием (interprocess communication) и является объектом постоянных исследований. Межпроцессорное взаимодействие может иметь самые разные формы. Одна из них (рис. 2) —модель «клиент/сервер» (client/server model) — широко применяется как для взаимодействия компонентов операционной систем, так и в организации компьютерных сетей. Согласно этой модели, каждый компонент выступает в роли клиента, посылающего запросы другим компонентам, или же в роли сервера, отвечающего на запросы, поступившие от клиентов. Например, система управления файлами функционирует как сервер, предоставляющий доступ к файлам в соответствии с запросами, поступающими от различных клиентов. Построенное в соответствии с этой моделью взаимодействие между процессами внутри операционной системы предусматривает поступление запросов от процессов, выполняющих роль клиентов, и предоставление ответов на них другими процессами, играющими роль серверов.
Рисунок 2 - Модель “клиент/сервер”
При разработке программного обеспечения соблюдение принципов модели "клиент/сервер" позволяет четко определить роли отдельных его элементов. Клиент просто посылает запросы серверам и ожидает поступления ответов, а сервер выполняет обслуживание поступивших запросов и посылает ответы клиентам. Роль сервера не зависит от того, функционирует ли клиент на этой же машине или на удаленной, соединенной с данной машиной через сеть. Различия существуют в программном обеспечении, используемом для их взаимодействия, но не в клиенте или сервере. В результате, если компоненты некоторой программной системы будут организованы как клиенты и серверы, то они смогут выполнять свои функции независимо от того, функционируют ли они на одной машине или на различных машинах, разделенных огромным расстоянием (рис. 3). Поэтому, если программное обеспечение, образующее нижний уровень системы, предоставляет средства обмена запросами и ответами на них, серверы и клиенты могут быть распределены по машинам в любой конфигурации, как это будет удобнее в данной сети.
Рисунок 3 - Идентичность схемы взаимодействия клиентов и серверов, функционирующих на одной и той же машине и на разных машинах
Желание установить единообразную систему отправки сообщений, которая сможет поддерживать такую распределенную систему в компьютерной сети, является основополагающей целью ряда стандартов и спецификаций, известных как CORBA (Common Object Request Broker Architecture — архитектура брокеров запросов общих объектов). Спецификация CORBA включает систему стандартов, регламентирующих сетевые взаимодействия элементов программного обеспечения, называемых объектами (такими как клиенты или серверы). Она была разработана группой OMG (Object Management Group — группа по управлению объектами), представляющей собой консорциум фирм-производителей аппаратного и программного обеспечения, а также пользователей, заинтересованных в расширении сферы применения объектно-ориентированной технологии, с которой мы познакомимся в главе 5 и к которой будем неоднократно возвращаться в последующих главах.
Общей задачей всех компонентов ядра операционной системы является распределение машинных ресурсов между процессами в системе. Здесь понятие ресурсы используется в широком смысле и включает как периферийные устройства, так и ресурсы самой машины. Программа управления файлами отвечает как за организацию доступа к уже существующим файлам, так и за распределение места на диске при создании новых файлов. Программа управления памятью распределяет свободные области памяти. Планировщик распределяет место в таблице процессов, а диспетчер — кванты времени. На первый взгляд задача распределения может показаться несложной. Однако если присмотреться, можно обнаружить несколько проблем, способных привести к сбоям в недостаточно тщательно разработанной системе. Не забывайте, что сама по себе машина не думает, а лишь следует имеющимся инструкциям. Поэтому для создания надежной операционной системы следует разработать алгоритмы, учитывающие все существующие аспекты выполняемой работы, какими бы незначительными они не казались.
Семафоры. Представим себе операционную систему с разделением времени, управляющую работой машины с одним принтером. Если процессу требуется напечатать полученные результаты, он должен запросить у операционной системы доступ к драйверу принтера. Получив запрос, операционная система должна решить, следует ли его удовлетворять, исходя из того, используется ли принтер в данный момент другим процессом. Если принтер свободен, операционная система может удовлетворить запрос и разрешить процессу продолжить свою работу; в противном случае она должна ответить на запрос отказом и, возможно, перевести опрос в состояние ожидания, которое будет продолжаться до тех пор, пока принтер вновь не будет доступен. Если доступ к принтеру будет предоставлен двум процессам одновременно, полученные результаты будут неудовлетворительны для каждого из них.
Чтобы управлять доступом к принтеру, операционная система должна следить, занят ли принтер в данный момент или нет. Одним из возможных решений может быть использование флажка, который в данном контексте будет представлять собой бит памяти, состояние которого будет означать занят или свободен, а не просто 1 или 0. Если значение флажка "свободен", то это означает, что принтер доступен, а если "занят", это указывает на то, что принтер уже предоставлен некоторому процессу. На первый взгляд использование такого подхода не должно вызывать каких-либо непредвиденных проблем. Операционная система просто проверяет состояние флажка при каждом поступлении запроса на предоставление доступа к принтеру. Если флажок находится в состоянии "свободен", то запрос удовлетворяется и операционная система изменяет значение флажка на "занят". Если текущее значение флажка "занят", то операционная система переводит процесс, направивший запрос, в состояние ожидания. Каждый раз, когда очередной процесс заканчивает работу с принтером, операционная система или предоставляет принтер ожидающему процессу, или, если ожидающих процессов нет, просто изменяет значение флажка на «свободен».
Хотя это решение выглядит вполне удовлетворительным, оно заключает в себе проблему. Задача проверки и, возможно, установки состояния флажка решается операционной системой за несколько машинных шагов. Следовательно, вполне возможно, что выполнение этой задачи будет прервано после того, как будет установлено, что флажок в состоянии «свободен», но еще до того, как его состояние будет изменено на «занят». В результате возможно возникновение следующей последовательности событий.
Предположим, что в данный момент времени принтер доступен и некоторый процесс запрашивает его использование. Система проверяет соответствующий флажок и обнаруживает, что он находится в состоянии «свободен», т.е. принтер доступен. Однако в этот момент выполнение процесса прерывается, и другой процесс начинает использовать выделенный ему квант времени. Он также запрашивает обращение к принтеру. Состояние флажка еще раз проверяется и обнаруживается, что он по-прежнему имеет значение «свободен», так как выполнение предыдущего процесса было прервано прежде, чем операционная система успела изменить значение флажка. В результате операционная система разрешает использовать принтер и второму процессу. Через некоторое время первый процесс возобновляет свою работу с того места, где он был приостановлен, т.е. непосредственно после того, как операционная система обнаружила, что флажок имеет значение «свободен». В результате операционная система разрешит первому процессу продолжить работу и предоставит ему доступ к принтеру. В итоге два процесса одновременно будут использовать один и тот же принтер.
Проблема состоит в том, что задача проверки и, возможно, установки значения флажка должна выполняться без прерываний. Одним из решений может быть использование команд запрета прерываний и команд разрешения прерываний, имеющихся в большинстве машинных языков. Если операционная система начнет процедуру проверки состояния флажка с команды, запрещающей выдачу прерываний в системе, и закончит ее командой, вновь разрешающей прерывания, то как только эта процедура будет начата, выполнение ее уже никогда не сможет быть прервано каким-либо другим процессом.
Другой подход к решению этой проблемы состоит в использовании команды test-and-set (проверить и установить), имеющейся во многих машинных языках. По этой команде центральному процессору предписывается считать значение флажка, проанализировать полученное значение, а затем при необходимости установить новое значение — и все это в пределах одной машинной команды. Преимущество этого варианта заключается в том, что центральный процессор, прежде чем проанализировать наличие прерывания, всегда завершает выполнение текущей команды, и выполнение задачи проверки и установки флажка не может быть прервано, если она реализована в виде одной команды.
Реализованный таким образом флажок называется семафором (semaphore). Это напоминает железнодорожное сигнальное устройство, используемое для управления доступом к определенному участку пути. Фактически в системах программного обеспечения семафоры используются почти так же, как и на железнодорожных линиях. Участку пути, на котором может находиться только один состав, соответствует последовательность команд, которая может выполняться одновременно только одним процессом. Такая последовательность команд называется критической областью (critical region). Требование о том, что в любой заданный момент только один процесс может выполнять команды критической области, называют взаимным исключением (mutual exclusion). Типичным способом реализации взаимного исключения для некоторой критической области является защита этой области с помощью семафора. Чтобы войти в критическую область, процесс должен удостовериться, что семафор открыт, и затем изменить его значение на "закрыт" еще до того, как войдет в критическую область. При выходе из критической области процесс должен вновь открыть семафор.
Взаимная блокировка. Другой проблемой, которая может иметь место при распределении ресурсов, является взаимная блокировка (deadlock). Это состояние, при котором дальнейшая работа двух или нескольких процессов взаимно заблокирована, так как каждый из них ожидает доступа к ресурсам, которые уже предоставлены другому. Например, один процесс может иметь доступ к принтеру, но ожидать доступа к накопителю на магнитных лентах, в то время как другой уже получил доступ к накопителю на магнитных лентах, но ожидает освобождения принтера. Другим примером является ситуация, когда процессы создают новые процессы, предназначенные для выполнения подзадач. Если у планировщика уже нет свободного места в таблице процессов, а каждому из процессов в системе для завершения своей задачи необходимо создать дополнительный процесс, то ни один из процессов не сможет продолжить свою работу. Эта и подобные ситуации (рис. 4) могут серьезно нарушить работу системы.
Рисунок 4 - Взаимная блокировка
Анализ причин появления взаимных блокировок показывает, что такие ситуации возможны только тогда, когда удовлетворены следующие три условия.
1. В системе имеет место конкуренция за использование неразделяемых ресурсов.
2. Ресурсы запрашиваются частями — процесс, уже получив некоторые ресурсы, продолжает запрашивать другие.
3. Предоставленный ресурс не может быть отобран принудительно. Смысл выделения этих трех условий состоит в том, что проблема возникновения взаимной блокировки может быть решена посредством устранения любого из них. В общем случае методы, предназначенные для подавления третьего условия, относятся к категории схем обнаружения взаимных блокировок с последующей коррекцией. При данном подходе считается, что тупиковые ситуации возникают настолько редко, что не стоит тратить усилия на предотвращение этой проблемы. Суть метода состоит в обнаружении ситуации взаимной блокировки, когда она уже возникла, и устранении ее посредством отбора некоторых предоставленных ресурсов. Приведенный выше пример с заполненной до отказа таблицей процессов можно отнести к этому классу. Как правило, системный администратор устанавливает размер таблицы процессов достаточно большим для данной конкретной системы. Если взаимная блокировка по причине переполнения таблицы процессов все же возникнет, то администратор просто использует свое право «суперпользователя», чтобы удалить (технический термин — убить) некоторые из процессов. В результате освобождается место в таблице процессов, после чего оставшиеся процессы смогут продолжить выполнение своих заданий.
Методики, нацеленные на устранение двух первых условий, относятся к схемам исключения тупиковых ситуаций. Одна из них, например, позволяет исключить второе условие за счет того, что каждый процесс должен запрашивать все необходимые ему ресурсы сразу. Другая, возможно более утонченная методика, направлена на устранение первого условия, но не за счет простого запрета конкуренции, а за счет превращения неделимых ресурсов в разделяемые. Например, предположим, что рассматриваемым ресурсом является принтер, и множество процессов запрашивают доступ к нему. Каждый раз, когда процесс запрашивает доступ к принтеру, система предоставляет ему этот доступ. Но вместо того чтобы подключить процесс непосредственно к драйверу принтера, операционная система подключает его к драйверу логического устройства, записывающего предназначенную для печати информацию на диск, вместо того чтобы отправить ее непосредственно на принтер. В результате каждый процесс выполняется нормальным образом, полагая, что он имеет доступ к принтеру. Позднее, когда принтер освободится, операционная система может переслать данные с диска на принтер. В этом случае операционная система придала неразделяемому ресурсу вид разделяемого, создав иллюзию наличия в системе более чем одного принтера. Подобная методика предварительного сохранения выводимых данных в целях ожидания подходящего момента для их действительного вывода получила название спулинга (spooling). В настоящее время она весьма распространена в операционных системах для любых платформ.
Безусловно, при конкуренции процессов за машинные ресурсы возникают и другие проблемы. Например, программа управления файлами должна предоставлять доступ к одному и тому же файлу сразу нескольким процессам, если они только считывают данные этого файла. Однако если нескольким процессам в одно и то же время потребуется изменить содержимое файла, это может привести к конфликтной ситуации. Поэтому программа управления файлами должна предоставлять доступ к файлам с учетом конкретных потребностей процессов, в каждый момент позволяя сразу нескольким процессам иметь доступ для чтения файла, но разрешая только одному процессу иметь доступ для записи в файл. Некоторые системы допускают разделение файла на части, в результате чего различные процессы получают возможность одновременно изменять различные части одного файла. Кроме того, могут возникать и другие проблемы, требующие своего решения. Например, как проинформировать процессы, получившие доступ для чтения, о том, что процесс с доступом для записи изменяет файл?