Для каждой ОС существует набор базовых понятий:
процесс, память, файлы.
Процессом называется программа в момент выполнения. С каждым процессом
связывается адресное пространство — список адресов памяти от минимума
(обычно нуля) до некоторого максимума, которые процесс может прочесть и в
которые он может писать. Адресное пространство содержит саму программу, данные
к ней и ее стек. Стек — упорядоченный набор элеменов, при обращении к которым
можно получить доступ лишь к одному из элементов, который называется вершиной
стека. С каждым процессом связывается набор регистров, включая счетчик команд,
указатель стека и другие аппаратные регистры, информация, необходимая для
запуска программы.
Вся информация о каждом процессе хранится
в таблице процессов, представляющей собой массив (или связанный список)
структур. Приостановленный процесс состоит из собственно адресного
пространства, называемого образом памяти и компонентов таблицы, содержащей
регистры
Главными системными вызовами, управляющими процессами,
являются вызовы, связанные с созданием и окончанием процессов. Другие системные
вызовы предназначаются для запросов о
предоставлении дополнительной памяти (или освобожденной неиспользуемой памяти),
ожидании завершения дочерних процессов. Если процесс может создавать другие
процессы (называемые дочерними процессами), а те процессы в свою очередь
другие процессы получается дерево процессов.
Связанные процессы — это те процессы, которые объединены для выполения
некоторой задачи, им нужно передавать данные от одного процесса к другому и
синхронизировать свою деятельность. Такая связь называется межпроцессорным
взаимодействием.
Процесс, который читает данные с
терминала, называется интерпретатором команд или оболочкой.
У каждого процесса есть идентификатор пользователя UID (User IDentification, присвоенный системным
администратором), запустившем его.
Дочерний процесс получает тот же UID, что и родитель. Пользователи могут
становиться членами групп, каждый из которых имеет идентификатор группы (GID, Group IDentification).
Пользователь с особым идентификатором UID, называется в UNIX суперпользователем, он имеет особые полномочия и может
игнорировать правила защиты.
Взаимоблокировка. Когда взаимодействуют два или более
процессов, они могут попадать в ситуации, неразрешимые без посторонней помощи.
Такая ситуация называется тупиком, тупиковой ситуацией или взаимоблокировкой.
Управление памятью.
В простых ОС в конкретный момент времени в
памяти находится только одна программа, чтобы запустить другую, надо выгрузить
первую и на ее место загрузить другую. В других ОС в памяти могут находиться
несколько программ, чтобы они не мешали друг другу и ОС, существует специальный
механизм, который находится в аппаратуре, но управляется ОС. Обычно под каждый процесс отводится некоторый
набор адресов, если же адресное пространство процесса окажется больше, чем
оперативная память компьютера в настоящее время существует метод, называемый виртуальной
памятью, при котором ОС держит часть адресов в оперативной памяти, а часть
на диске и меняет их при необходимости местами.
Память. В отношении памяти ОС должна следить
за тем, чтобы ни один из независимых процессов не смог изменить содержимое
памяти, отведенное другому процессу, и наоборот.
ОС должна:
— повышать эффективность работы вычислительной системы,
выделяя заданиям тот объем, который необходим;
— обеспечивать поддержку модульного программирования,
давая программисту возможность определять модули программы, а также давать возможность
динамически их создавать, уничтожать, изменять размер;
— гарантировать защиту и контроль доступа, определяя
каким образом различные пользователи могут осуществлять доступ к различным
областям памяти;
— обеспечивать долгосрочное хранение информации в
течение длительного времени после выключения компьютера.
Все эти требования ОС выполняют с помощью средств
виртуальной памяти и файловой системы.
Принципы работы с виртуальной памятью были разработаны
таким образом, чтобы задания нескольких пользователей, выполняясь программно,
могли одновременно присутствовать в основной памяти.
При такой организации нет задержки между их
выполнением: как только один из процессов заносится на вспомогательное
запоминающее устройство, считывается следующий процесс. Для их компактного
расположения в памяти разработаны системы со страничной организацией памяти,
при которой процесс разбивается на блоки фиксированного размера, которые
называются страницами. Обращение программы к слову памяти происходит по
виртуальному адресу, который состоит из номера страницы и смещения относительно
ее начала. Система разбивки на страницы обеспечивает динамическое соответствие
между виртуальным адресом, использующимся программой и реальным или физическим
адресом основной памяти.
Адресация виртуальной
памяти
Рассмотрим концепцию адресации в схеме виртуальной
памяти. Хранилище состоит из основной памяти, открытой для прямого доступа,
осуществляемого с помощью машинных команд, а также более медленной вспомогательной
памяти, доступ к которой осуществляется косвенно путем загрузки блоков в
основную память. Между процессором и памятью находятся аппаратные средства
преобразования адреса. Программы обращаются к ячейкам памяти посредством
виртуальных адресов, преобразующихся в ходе обращения в реальные адреса памяти.
Ели происходит обращение к виртуальному адресу, который не загружен в основную
память, то один из блоков реальной памяти меняется местами с нужным блоком,
который находится во вспомогательной памяти. Во время этого обмена процесс,
который обращается к данному адресу должен быть приостановлен. Задача
разработки такого механизма преобразования адресов, который бы не требовал
больших дополнительных ресурсов и такого размещения данных в хранилище, которое
позволяло бы обеспечить минимум перемещения данных между различными уровнями
памяти, возлагается на разработчика ОС.
Ввод-вывод данных осуществляется подсистемой ОС для
управления этими устройствами, некоторые из программ ввода-вывода являются
независимыми от устройств, другая часть (к ним относятся драйверы устройств)
предназначена для определенных устройств ввода-вывода.
Файловая система — ключевое понятие, поддерживаемое
виртуально всеми ОС. Так, для создания, удаления, чтения или записи файлов
используются системные вызовы. Для хранения файлов ОС используют понятие
каталога, как способ объединения файлов в группы. Иерархии процессов и файлов
организованы в виде деревьев, на этом сходство заканчивается. Различия — по
уровню, времени, защите, управлению. Существует важное понятие в UNIX — смонтированная файловая система.
Перед вызовом системной процедуры mount корневая файловая система на жестком
диске (Рис. 1а) и вторая файловая система на гибком диске существуют раздельно.
UNIX не
позволяет присоединить к началу пути название диска или его номер, так как это
привело бы к жесткой зависимости устройств, которой ОС должна избегать. Вместо
этого системный вызов mount позволяет присоединять файловую
систему на гибком диске к корневой системе в том месте, где этого захочет
программа. При этом файловые системы почти всегда устанавливаются в пустые каталоги
(в данном случае b
). В UNIX существуют также специальные файлы для устройств ввода-вывода. Они
бывают блочные специальные файлы и символьные специальные файлы.
Блочные специальные файлы используются для моделирования устройств, состоящих
из набора произвольно адресуемых блоков, таких как диски. Символьные
специальные файлы используются для моделирования принтеров, модемов и других
устройств, которые принимают или выдают поток символов.
Канал в UNIX представляет собой псевдофайл, который используется
для связи двух процессов. Соединение между процессами в UNIX выглядит очень похожим на обычное
чтение и запись файлов. Только специальный системный вызов может определить,
что выходной файл — не реальный файл, а канал.
Безопасность. Для защиты файлов в UNIX им присваивается 9-битовый двоичный
код. Этот код защиты полей состоит из 3 полей по 3 байта: одно — для владельца;
второе — для других членов; третье — для всех остальных. Эти три бита
называются rvx-битами (read, write, execute). Кроме защиты файлов, существует еще
множество других вопросов безопасности: защита системы от нежелательных гостей,
вирусов и т.д.
Оболочка. ОС представляет собой программу,
выполняющую системные вызовы. Редакторы, компиляторы, компоновщики, командные
интерпретаторы — не являются частью ОС. Оболочка (например shell для UNIX или командный интерпретатор) не
входит в ОС, но пользуется многими функциями ОС через системные вызовы.
Например: когда какой-либо пользователь входит в
систему, запускается оболочка (например shell), которая начинает работу с печати
приглашения (prompt) — знака доллара. Если пользователь
напечатет date оболочка создаст дочерний процесс и запустит программу date. После завершения дочернего процесса
оболочка опять печатает приглашение и т. д. Если пользователь наберет знак
& после команды, оболочка не будет ждать окончания ее выпонения. В этом
случае она напишет новое приглашение, то есть в результате команды cat file1 file2 file3 | sort > / dev lp & (concatenate — объединить 3 файла, послать выходные
данные программе sort, которая расставит все строки в алфавитном порядке и перенаправит в файл,
обозначающий принтер), сортировка запустится как фоновое задание, разрешая
пользователю продолжать работу во время выполнения сортировки.
Системные вызовы. Интерфейс между ОС и программами
пользователя определяется набором системных вызовов, предоставляемых ОС.
Механизм обращения к системным функциям является в высокой степени
машинно-зависимым и должен реализовываться на ассемблере или через библиотеки
процедур, делающие возможным обращение к системным процедурам из программ на С
и других языках. Выполнение системного вызова похоже на осуществление вызова
процедуры, только первый проникает в ядро, а второй этого не делает. Чтобы
прояснить механизм системных вызовов, рассмотрим системный вызов read с тремя параметрами: первый — задает
имя файла, второй — указывает на буфер, третий — задает количество байтов,
которые надо прочитать. Задается он (как обычно все системные вызовы) из
программы на С с помощью вызова библиотечной процедуры: count = read (fd, buffer, n bytes). Системный
вызов (и библиотечная процедура) возвращает количество прочитанных байтов в
переменной count.
Обычно эта величина совпадает с параметром n bytes, но может быть меньше, если в
процессе чтения процедуры встречается конец файла. Если системный вызов не
может быть выполнен из-за неправильных параметров или из-за дисковой ошибки,
значение счетчика count устанавливается равным –1, а номер ошибки помещается в глобальную переменную
errno.
Системные вызовы выполняются за серию шагов: сначала вызывающая программа
помещает параметры в стек
Компиляторы C и C++ помещают параметры в стек в обратном порядке. Первый и
третий параметры передаются по значению, а второй параметр по ссылке (на это
указывает символ &), то есть передается адрес буфера. Затем следует вызов
библиотечной процедуры (шаг 4). Библиотечная процедура (как правило, написанная
на ассемблере) обычно помещает номер системного вызова туда, где его ожидает ОС
(например в регистр — шаг 5). Затем она выполняет команду TRAP (эмулированное прерывание) для
переключения из пользовательского режима в режим ядра и начинает выполнение с
фиксированного адреса внутри ядра (шаг 6). Запускаемая программа ядра проверяет
номер системного вызова и затем отправляет его нужному обработчику, используя
таблицу указателей на обработчики системных вызовов, индексированную по номерам
вызовов (шаг 7). В этом месте начинает функционировать обработчик системных
вызовов (шаг 8). Как только он завершает свою работу, управление может
возвращаться в пространство пользователя к библиотечной процедуре, к команде,
следующей за командой TRAP (шаг 9). Эта процедура передает управление программе
пользователя (шаг 10). Чтобы закончить работу, программа пользователя должна
очистить стек, как это делается после каждого вызова процедуры (шаг11).
Учитывая, что стек растет вниз, последняя команда увеличивает указатель стека
ровно настолько, насколько нужно для удаления параметров, помещенных в стек
перед запросом read. После чего программа может продолжить работу.
Существуют системные вызовы, предназначенные для
управления процессами, файлами, каталогами, вызовы изменения текущего каталога,
защиты, уничтожения процессов, управления временем и многих других.
Рассмотрим разницу системных вызовов
UNIX и Windows, отличающихся моделями программирования. Программы UNIX состоят из кода, который выполняет те
или иные действия, обращаясь к системе с системными запросами для
предоставления ему конкретных услуг. В противоположность этому программы в Windows обычно приводятся в действие
событиями. Основной модуль программы ждет, когда произойдет какое-либо событие,
затем вызывает процедуру для его обработки. Типичными событиями являются:
нажатие клавиши мыши или клавиатуры, передвижение мыши, появление гибкого диска
в дисководе. В Windows тоже есть системные вызовы. В UNIX они идентичны библиотечным процедурам
(всего в стандарте POSIX около 100 процедурных вызовов).
В Windows фактические системные вызовы и запускающиеся для их выполнения
библиотечные вызовы полностью разделены. Корпорацией Microsoft определен набор процедур, называемый Win 32 API (Application Program Interface — интерфейс прикладных программ).
Предполагается, что программисты должны использовать его для вызова служб ОС.
Этот интерфейс частично поддерживается всеми версиями Windows, начиная с Windows 95.
Количество вызовов в Win 32 API исчисляется тысячами. Некоторые из
них являются системными, некоторые целиком работают в пространстве пользователя.
Причем, вызов, считающийся системным в одной версии Windows, может обрабатываться в пространстве
пользователя и наоборот.
Другое различие заключается в том, что в UNIX графический интерфейс пользователя
(например XWindows или Motif) запускается целиком в пользовательском пространстве. Поэтому для вывода
на экран достаточно системного вызова write и несколько других незначительных
вызовов.
В противоположность этому Win 32 API имеет огромное количество вызовов для
управления окнами, геометрическими фигурами, текстом, шрифтами, диалоговыми
окнами и другими элементами графического интерфейса. В том случае, когда
графическая подсистема запускается в режиме ядра (это верно для большинства
версий Windows),
вызовы являются системными, в противоположном случае — только библиотечными.
С добавлением в ОС новых функций, а также с ростом
возможностей управляемого ОС аппаратного обеспечения и его разнообразия
возрастает степень их сложности. Для получения общего представления об ОС
представим пример обобщенной модели иерархической ОС.
Уровень 1. В него входят электронные схемы;
объектами этого уровня являются регистры, ячейки памяти и логические элементы.
Над этими объектами выполняются различные действия, такие как очистка
содержимого регистра или считывание ячейки памяти.
Уровень 2. Набор команд процессора. В число
операций, выполняемых на этом уровне, входят те, которые допускаются набором
команд машинного языка, например сложение, вычитание, загрузка значения из
регистра или сохранение в нем.
Уровень 3. Содержит процедуры (подпрограммы),
операции вызова и возврата.
Уровень 4. Уровень прерываний, которые заставляют
процессор сохранить текущий контекст и выполнить подпрограмму обработки
прерывания.
Первые 4 уровня не являются частями ОС, они составляют
аппаратное обеспечение процессора, первые элементы ОС — программы обработки
прерывания. Вплотную к ОС приближаемся лишь на 5 уровне, где возникают задачи,
связанные с многозадачностью.
Уровень 5 (примитивные процессы). На этом уровне вводится понятие
процесса, под которым подразумевается работающая программа, сохранение
содержимого регистров аппаратного обеспечения для переключения с одного
процесса на другой. Если же процессы должны взаимодействовать между собой,
необходим механизм их синхронизации. На этом уровне одной из важнейших
концепций устройства ОС является семафор — простейший способ передачи сигналов.
Уровень 6 (локальная вторичная
память). Компоненты
этого уровня взаимодействуют со вспомогательными запоминающими устройствами
компьютера. На этом уровне происходит позиционирование считывающих головок и физическая
передача блоков данных. Для планирования работы и уведомления процесса о
завершении запрошенной операции уровень 6 использует компоненты уровня 5.
Объектами на этом уровне выступают блоки данных, каналы устройств; чтение,
запись, распределение, выборка — являются примерами операций.
Уровень 7 (виртуальная память). Создает логическое адресное пространство
процессов. Уровень организует виртуальное адресное пространство в виде блоков,
которые могут перемещаться между основной памятью и вспомогательным
запоминающим устройством. Широко распространены следующие схемы: использование
страниц фиксированного размера, использование сегментов переменного размера и
комбинация тех и других. Если нужный блок отсутствует в основной памяти, то
данный уровень передает уровню 6 запрос о передаче этого блока.
До сих пор речь шла только о взаимодействии ОС с
процессором. Компоненты ОС, относящиеся к 8 и более высоким уровням, вступают
во взаимодействие с внешними объектами, такими как периферийные устройства или
с сетью и компьютерами, подключенными к сети.
Уровень 8 (коммуникации). Отвечает за обмен информацией и сообщениями
между процессами. На этом уровне происходит более богатый обмен информацией,
чем на уровне 5, который обеспечивает работу первичного сигнального механизма
для синхронизации процессов. Одним из наиболее мощных инструментов подобного
типа является конвейер, представляющий собой логический канал передачи данных
между процессами. Конвейер определяется как канал, передающий вывод одного
процесса на вход другого или (и) для связи с процессом внешних устройств или
файлов. Примерами операций на этом уровне являются: создание, удаление,
открытие, закрытие, чтение, запись; объектами — конвейеры.
Уровень 9 (файловая система). Обеспечивает долгосрочное хранение
файлов. На этом уровне данные, хранящиеся на вспомогательном запоминающем
устройстве, рассматриваются как абстрактные объекты переменной длины, в
противоположность аппаратно-зависимому рассмотрению вторичной памяти как набора
дорожек, секторов и блоков фиксированного размера, присущему уровню 6;
объектами на этом уровне выступают файлы; примерами операций: создание,
удаление, открытие, закрытие, чтение, запись.
Уровень 10 (устройства). Представляет доступ к внешним
устройствам с помощью стандартных интерфейсов. Объектами на этом уровне
являются: внешние устройства (принтер, монитор, клавиатура); операциями:
открытие, закрытие, чтение, запись.
Уровень 11 (каталоги). Поддерживает связь между внешними и
внутренними идентификаторами системных ресурсов и объектов.
Внешний идентификатор — имя, которое может использоваться
приложением или пользователем.
Внутренний идентификатор — это адрес или другой индикатор, используемый
нижними уровнями ОС для обнаружения объекта и управления им. Эта связь
поддерживается с помощью каталога, который включает в себя не только взаимное
отображение внешних и внутренних идентификаторов, но и такие характеристики,
как, например, права доступа.
Уровень 12 (пользовательские
процессы).
Представляет полнофункциональные средства поддержки процессов. Возможности
этого уровня намного превосходят возможности уровня 5 (на котором
поддерживается только содержимое регистров процессора, имеющее отношение к
процессу и логика диспетчеризации процессов). На 12 уровне эта информация
используется для упорядоченного управления процессами. Сюда же относится и
виртуальное адресное пространство процессов, список объектов и процессов, с
которыми оно может взаимодействовать; правила, ограничивающие это
взаимодействие; параметры, переданные процессам при их создании и другие
характеристики процессов, которые могут быть использованы ОС для управления.
Примерами операций на этом уровне являются: завершение
процесса, приостановка, возобновление работы.
Уровень 13 (оболочка). Обеспечивает взаимодействие ОС с
пользователем. Этот уровень называется оболочкой (shell), так как он отделяет пользователя от
деталей внутреннего устройства ОС с представляет ее пользователю как набор
сервисов. На этом уровне может быть реализован графический интерфейс,
предоставляющий пользователю возможность выбора команды с помощью меню и
отображающей результаты работы на экране. Объектами на этом уровне выступают
пользовательская среда программирования; операциями: инструкции командного
языка оболочки.
Архитектура
ОС
Любая сложная система должна иметь понятную и
рациональную структуру, то есть разделяться на части — модули, имеющие вполне
законченное функциональное назначение с четко оговоренными правилами
взаимодействия. Ясное понимание роли каждого отдельного модуля существенно
упрощает работу по модификации и развитию системы. Напротив, сложную систему
без хорошей структуры чаще проще разработать заново, чем модернизировать.
Функциональная сложность операционной системы неизбежно
приводит к сложности ее архитектуры, под которой понимают структурную
организацию ОС на основе различных программных модулей. Обычно в состав ОС
входят исполняемые и объектные модули стандартных для данной ОС форматов,
библиотеки разных типов, модули исходного текста программ, программные модули
специального формата (например, загрузчик ОС, драйверы ввода-вывода),
конфигурационные файлы, файлы документации, модули справочной системы и т. д.
Большинство современных операционных систем
представляют собой хорошо структурированные модульные системы, способные к
развитию, расширению и переносу на новые платформы. Какой-либо единой
архитектуры ОС не существует, но существуют универсальные подходы к
структурированию ОС.