Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ОСиС исправление Егор.docx
Скачиваний:
13
Добавлен:
25.11.2019
Размер:
439.29 Кб
Скачать

Структура операционных систем

Монолитная система

Монолитные системы (монолитное ядро, monolithic kernel).  В общем случае организация системы представляет собой простейшую структуру, когда компоненты операционной системы являются не самостоятельными модулями, а составными частями одной программы. Операционная система написана в виде набора процедур. При использовании такой техники каждая процедура системы имеет строго определенный интерфейс и возможность вызвать любую другую процедуру для выполнения поставленной задачи. Все процедуры работают в привилегированном режиме. Таким образом, монолитная система – это схема операционной системы, при которой все ее компоненты являются составными частями одной программы, используют общие структуры данных и взаимодействуют друг с другом путем непосредственного вызова процедур.

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

При обращении к системным вызовам, поддерживаемым операционной системой, параметры помещаются в строго определенные места – регистры или стек, после чего выполняется специальная команда прерывания, известная как вызов ядра или вызов супервизора. Эта команда переключает машину из режима пользователя в режим ядра и передает управление операционной системе (см. рис. 2.5, шаг 6). Затем операционная система проверяет параметры вызова, чтобы определить, какой системный вызов должен быть выполнен. После этого операционная система обращается к таблице как к массиву с номером системного вызова в качестве индекса. В k-м элементе таблицы содержится ссылка на процедуру обработки системного вызова k. 

В этой модели для каждого системного вызова имеется одна служебная процедура. Утилиты выполняют функции, которые нужны нескольким служебным процедурам. Монолитная структура – старейший способ организации операционных систем. Примером таких систем является большинство Unix систем.

Структура системы:

  1. Главная программа, которая вызывает требуемые сервисные процедуры.

  2. Набор сервисных процедур, реализующих системные вызовы.

  3. Набор утилит, обслуживающих сервисные процедуры.

Простая модель монолитной системы

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

Этапы обработки вызова:

  • Принимается вызов

  • Выполняется переход из режима пользователя в режим ядра

  • ОС проверяет параметры вызова для того, чтобы определить, какой системный вызов должен быть выполнен

  • После этого ОС обращается к таблице, содержащей ссылки на процедуры, и вызывает соответствующую процедуру.

Многоуровневая структура ОС

Обобщением предыдущего подхода является организация ОС как иерархии уровней. Уровни образуются группами функций операционной системы - файловая система, управление процессами и устройствами и т.п. Каждый уровень может взаимодействовать только со своим непосредственным соседом - выше- или нижележащим уровнем. Прикладные программы или модули самой операционной системы передают запросы вверх и вниз по этим уровням.

Первой многоуровневой системой была система THE, созданная в Technische Hogeschool Eindhoven (Нидерланды) Э. Дейкстроем (Е.W. Dijkstra) и его студентами в 1968 г. Она была простой пакетной системой для голландского компьютера Electrologica X8, память которого состояла из 32 Кб 27-разрядных слов. Система включала 6 уровней (рис. 2.7):

–   уровень 0 занимался распределением времени процессора, переключая процессы при возникновении прерывания или при срабатывании таймера, т. е. обеспечивал базовую многозадачность процессора;

–   уровень 1 управлял памятью, он выделял процессам пространство в оперативной памяти и на магнитном барабане объемом 512 Кб слов для тех частей процессов (страниц), которые не помещались в оперативной памяти;

–   уровень 2 управлял связью между консолью оператора и процессами, процессы, расположенные выше этого уровня, имели свою собственную консоль оператора;

–   уровень 3 управлял устройствами ввода-вывода и буферизовал потоки информации к ним и от них, поэтому любой процесс выше уровня 3, вместо того чтобы работать с конкретными устройствами, мог обращаться к абстрактным устройствам ввода-вывода, обладающим удобными для пользователя характеристиками;

–   уровень 4 был предназначен для работы пользовательских программ, которым не нужно было заботиться ни о процессах, ни о памяти, ни о консоли, ни об управлении устройствами ввода-вывода;

–   уровень 5 предназначался для процесса системного оператора.

Уровни

Функции

5

4

3

2

1

0

Оператор

Программы пользователя

Управление вводом-выводом

Связь оператор-процесс

Управление памятью и барабаном

Распределение процессора и многозадачность

 

Рис. 2.7. Структура операционной системы THE

Дальнейшее обобщение многоуровневой концепции было сделано в операционной системе MULTICS, где уровни представляли серию концентрических колец, причем внутренние кольца являлись более привилегированными, чем внешние. Когда процедура внешнего кольца «хотела» вызвать процедуру кольца, лежащего внутри, она должна была выполнить эквивалент системного вызова, т. е. команду TRAP, параметры которой тщательно проверяются перед вызовом. Хотя операционная система MULTICS являлась частью адресного пространства каждого пользовательского процесса, аппаратура обеспечивала защиту данных на уровне сегментов памяти, разрешая или запрещая доступ к индивидуальным процедурам (сегментам памяти) для записи, чтения или выполнения.

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

 

Пример структуры многоуровневой системы

Преимущества:

  • Высокая производительность

Недостатки:

  • Большой код ядра, и как следствие большое содержание ошибок

  • Ядро плохо защищено от вспомогательных процессов

Пример реализации многоуровневой модели UNIX.

 

 

Структура ОС UNIX

 

 

Ядро ОС UNIX

 

Пример реализации многоуровневой модели Windows

 

Структура Windows 2000

Модель экзоядра

Развив идею виртуальной машины VM/370, когда каждый пользователь получает точную копию настоящей машины, исследователи из Массачусетского технологического института изобрели новую систему. В этой системе реализован принцип обеспечения каждого пользователя абсолютной копией реального компьютера, но с подмножеством ресурсов. Например, одна виртуальная машина может получить блоки на диске с номерами от 0 до 1023, следующая – от 1024 до 2047 и т. д. На нижнем уровне в режиме ядра работает программа – экзоядро (exokernel), в задачу которой входит распределение ресурсов для виртуальных машин и проверка их использования (отслеживание попыток машин использовать чужой ресурс). Каждая виртуальная машина на уровне пользователя может работать с собственной операционной системой, как наVM/370 или на виртуальных машинах 8086-х для Pentium, с той разницей, что каждая машина ограничена набором ресурсов, которые она запросила и которые ей были предоставлены. Преимущества подхода:

–   отделяется многозадачность (в экзоядре) от операционных систем пользователя (в пространстве пользователя) с меньшими затратами, так как для этого экзоядру необходимо только не допускать вмешательства одной виртуальной машины в работу другой;

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

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

 

1.4.4 Микроядерная архитектура (модель клиент-сервер)

Эта модель является средним между двумя предыдущими моделями.

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

В этой модели вводятся два понятия:

  1. Серверный процесс (который обрабатывает запросы)

  2. Клиентский процесс (который посылает запросы)

В задачу ядра входит только управление связью между клиентами и серверами.

 

Модель клиент-сервер

Преимущества:

  • Малый код ядра и отдельных подсистем, и как следствие меньшее содержание ошибок.

  • Ядро лучше защищено от вспомогательных процессов.

  • Легко адаптируется к использованию в распределенной системе.

Недостатки:

  • Уменьшение производительности.

Понятия «процесс» и «поток»

Процесс (задача) - программа, находящаяся в режиме выполнения.

С каждым процессом связывается его адресное пространство, из которого он может читать и в которое он может писать данные.

Адресное пространство содержит:

  • саму программу

  • данные к программе

  • стек программы

С каждым процессом связывается набор регистров, например:

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

  • указатель стека

  • и д.р.

Во многих операционных системах вся информация о каждом процессе, дополнительная к содержимому его собственного адресного пространства, хранится в таблице процессов операционной системы:

Управление процессом

Управление памятью

Управление файлами

Регистры

Счетчик команд

Указатель стека

Состояние процесса

Приоритет

Параметры планирования

Идентификатор процесса

Родительский процесс

Группа процесса

Время начала процесса

Использованное процессорное время

Указатель на текстовый сегмент

Указатель на сегмент данных

Указатель на сегмент стека

Корневой каталог

Рабочий каталог

Дескрипторы файла

Идентификатор пользователя

Идентификатор группы

Чтобы поддерживать мультипрограммирование, ОС должна определить и оформить для себя те внутренние единицы работы, между которыми будет разделяться процессор и другие ресурсы компьютера. В настоящее время в большинстве операционных систем определены два типа единиц работы. Более крупная единица работы, обычно носящая название процесса, или задачи, требует для своего выполнения нескольких более мелких работ, для обозначения которых используют термины «поток», или «нить».

При использовании этих терминов часто возникают сложности. Это происходит в силу нескольких причин. Во-первых, — специфика различных ОС, когда совпадающие по сути понятия получили разные названия, например задача (task) в OS/2, OS/360 и процесс (process) в UNIX, Windows NT, NetWare. Во-вторых, по мере развития системного программирования и методов организации вычислений некоторые из этих терминов получили новое смысловое значение, особенно это касается понятия «процесс», который уступил многие свои свойства новому понятию «поток». В-третьих, терминологические сложности порождаются наличием нескольких вариантов перевода англоязычных терминов на русский язык. Например, термин «thread» переводится как «нить», «поток», «облегченный процесс», «минизадача» и др. Далее в качестве названия единиц работы ОС будут использоваться термины «процесс» и «поток». В тех же случаях, когда различия между этими понятиями не будут играть существенной роли, они объединяются под обобщенным термином «задача».

Очевидно, что любая работа вычислительной системы заключается в выполнении некоторой программы. Поэтому и с процессом, и с потоком связывается определенный программный код, который для этих целей оформляется в виде исполняемого модуля. Чтобы этот программный код мог быть выполнен, его необходимо загрузить в оперативную память, возможно, выделить некоторое место на диске для хранения данных, предоставить доступ к устройствам ввода-вывода, например к последовательному порту для получения данных по подключенному к этому порту модему; и т. д. В ходе выполнения программе может также понадобиться доступ к информационным ресурсам, например файлам, портам TCP/UPD, семафорам. И, конечно же, невозможно выполнение программы без предоставления ей процессорного времени, то есть времени, в течение которого процессор выполняет коды данной программы.

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

В простейшем случае процесс состоит из одного потока, и именно таким образом трактовалось понятие «процесс» до середины 80-х годов (например, в ранних версиях UNIX) и в таком же виде оно сохранилось в некоторых современных ОС. В таких системах понятие «поток» полностью поглощается понятием «процесс», то есть остается только одна единица работы и потребления ресурсов — процесс. Мультипрограммирование осуществляется в таких ОС на уровне процессов.

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

Виртуальное адресное пространство процесса — это совокупность адресов, которыми может манипулировать программный модуль процесса. Операционная система отображает виртуальное адресное пространство процесса на отведенную процессу физическую память.

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

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

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

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

Во-вторых, решением является создание для одного приложения нескольких процессов для каждой из параллельных работ. Однако использование для создания процессов стандартных средств ОС не позволяет учесть тот факт, что эти процессы решают единую задачу, а значит, имеют много общего между собой — они могут работать с одними и теми же данными, использовать один и тот же кодовый сегмент, наделяться одними и теми же правами доступа к ресурсам вычислительной системы. Так, если в примере с сервером баз данных создавать отдельные процессы для каждого запроса, поступающего из сети, то все процессы будут выполнять один и тот же программный код и выполнять поиск в записях, общих для всех процессов файлов данных. А операционная система при таком подходе будет рассматривать эти процессы наравне со всеми остальными процессами и с помощью универсальных механизмов обеспечивать их изоляцию друг от друга. В данном случае все эти достаточно громоздкие механизмы используются явно не по назначению, выполняя не только бесполезную, но и вредную работу, затрудняющую обмен данными между различными частями приложения. Кроме того, на создание каждого процесса ОС тратит определенные системные ресурсы, которые в данном случае неоправданно дублируются — каждому процессу выделяются собственное виртуальное адресное пространство, физическая память, закрепляются устройства ввода-вывода и т. п.

Из всего вышеизложенного, следует, что в операционной системе наряду с процессами нужен другой механизм распараллеливания вычислений, который учитывал бы тесные связи между отдельными ветвями вычислений одного и того же приложения. Для этих целей современные ОС предлагают механизм многопоточной обработки (multithreading). При этом вводится новая единица работы — поток выполнения, а понятие «процесс» в значительной степени меняет смысл. Понятию «поток» соответствует последовательный переход процессора от одной команды программы к другой. ОС распределяет процессорное время между потоками. Процессу ОС назначает адресное пространство и набор ресурсов, которые совместно используются всеми его потоками.

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

Итак, мультипрограммирование более эффективно на уровне потоков, а не процессов. Каждый поток имеет собственный счетчик команд и стек. Задача, оформленная в виде нескольких потоков в рамках одного процесса, может быть выполнена быстрее за счет псевдопараллельного (или параллельного в мультипроцессорной системе) выполнения ее отдельных частей. Например, если электронная таблица была разработана с учетом возможностей многопоточной обработки, то пользователь может запросить пересчет своего рабочего листа и одновременно продолжать заполнять таблицу. Особенно эффективно можно использовать многопоточность для выполнения распределенных приложений, например многопоточный сервер может параллельно выполнять запросы сразу нескольких клиентов.

Использование потоков связано не только со стремлением повысить производительность системы за счет параллельных вычислений, но и с целью создания более читабельных, логичных программ. Введение нескольких потоков выполнения упрощает программирование. Например, в задачах типа «писатель-читатель» один поток выполняет запись в буфер, а другой считывает записи из него. Поскольку они разделяют общий буфер, не стоит их делать отдельными процессами. Другой пример использования потоков — управление сигналами, такими как прерывание с клавиатуры (del или break). Вместо обработки сигнала прерывания один поток назначается для постоянного ожидания поступления сигналов. Таким образом, использование потоков может сократить необходимость в прерываниях пользовательского уровня. В этих примерах не столь важно параллельное выполнение, сколь важна ясность программы.

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

Состояние процессов

Существует три основных состояния процесса:

  • Выполнение (занимает процессор)

  • Готовность (процесс временно приостановлен, чтобы позволить выполняться другому процессу)

  • Ожидание (процесс не может быть запущен по своим внутренним причинам, например, ожидая операции ввода/вывода)

Рис. 3.2. Возможные переходы между состояниями.

1. Процесс блокируется, ожидая входных данных

2. Планировщик выбирает другой процесс

3. Планировщик выбирает этот процесс

4. Поступили входные данные

 

Переходы 2 и 3 вызываются планировщиком процессов операционной системы, так что сами процессы даже не знают о этих переходах. С точки зрения самих процессов есть два состояния выполнения и ожидания.

На серверах для ускорения ответа на запрос клиента, часто загружают несколько процессов в режим ожидания, и как только сервер получит запрос, процесс переходит из "ожидания" в "выполнение". Этот переход выполняется намного быстрее, чем запуск нового процесса.

Потоки (нити)

Понятие потока

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

 

Рис. 3.3. Сравнение многопоточной системы с однопоточной

 

Модель потока

С каждым потоком связывается:

  • Счетчик выполнения команд

  • Регистры для текущих переменных

  • Стек

  • Состояние

Потоки делят между собой элементы своего процесса:

  • Адресное пространство

  • Глобальные переменные

  • Открытые файлы

  • Таймеры

  • Семафоры

  • Статистическую информацию.  

В остальном модель идентична модели процессов. В POSIX и Windows есть поддержка потоков на уровне ядра. В Linux есть новый системный вызов clone для создания потоков, отсутствующий во всех остальных версиях системы UNIX. В POSIX есть новый системный вызов pthread_create для создания потоков. В Windows есть новый системный вызов Createthread для создания потоков.

 

Планирование процессов и потоков

Одной из основных подсистем мультипрограммной ОС, непосредственно влияющей на функционирование вычислительной машины, является подсистема управления процессами и потоками, которая занимается:

  1. их созданием и уничтожением,

  2. поддерживает взаимодействие между ними,

  3. распределяет процессорное время между несколькими одновременно существующими в системе процессами и потоками.

  4. синхронизация процессов (согласование скоростей потоков также очень важно для предотвращения эффекта «гонок» - когда несколько потоков пытаются изменить один и тот же файл, взаимных блокировок или других коллизий, которые возникают при совместном использовании ресурсов),

  5. ответственна за обеспечение процессов необходимыми ресурсами,

  6. обеспечивает освобождение выделенных ресурсов (закрываются все файлы, с которыми работал процесс, освобождаются области оперативной памяти, отведенные под коды, данные и системные информационные структуры процесса, выполняется коррекция всевозможных очередей ОС и списков ресурсов, в которых имелись ссылки на завершаемый процесс).

С точки зрения обеспечения ресурсами ОС выполняет следующие функции и задачи:

  1. назначение процессу ресурсов в единоличное пользование или в совместное пользование с другими процессами,

  2. выделение ресурсов процессу при его создании или динамически по запросам во время выполнения.

  3. обеспечение ресурсами процессу на все время его жизни или только на определенный период,

  4. обеспечение взаимодействия с другими подсистемами ОС, ответственными за управление ресурсами (подсистема управления памятью, подсистема ввода-вывода, файловая система).