Реферат: Разработка операционных систем
Понятие ортогональности
также встречается в операционных системах в различных формах. Одним из примеров
является системный вызов clone операционной системы Linux, создающий новый
поток. В качестве параметра этот вызов принимает битовый массив, задающий такие
режимы, как независимое друг от друга совместное использование или копирование
адресного пространства, рабочего каталога, дескрипторов файлов и сигналов. Если
копируется все, то мы получаем новый процесс, как и при использовании
системного вызова fork. Если ничего не копируется, это означает, что создается
новый поток в текущем процессе. Однако вероятно и создание промежуточных форм,
невозможных в традиционных системах UNIX. Разделение свойств и их
ортогональность позволяет получить более детальную степень управления.
Другое применение ортогональности
– разделение понятий процесса и потока в Windows 2000. Процесс представляет
собой контейнер для ресурсов, не более и не менее. Поток представляет собой
объект планирования. Когда один процесс получает дескриптор от другого
процесса, не имеет значения, сколько потоков у него есть. Когда планировщик
выбирает поток, не важно, какому процессу он принадлежит. Эти понятия
ортогональны.
Наш последний пример
ортогональности возьмем из операционной системы UNIX. Создание процесса
происходит здесь в два этапа: при помощи системных вызовов fork и exec.
Создание нового адресного пространства и заполнение его новым образом памяти в
данном случае разделены, что позволяет выполнить определенные действия между
этими этапами. В операционной системе Windows 2000 эти два этапа нельзя
разделить, то есть концепции создания нового адресного пространства и его
заполнения новым образом памяти не являются ортогональными в этой системе.
Последовательность системных вызовов clone и exec в системе Linux является еще
более ортогональной, так как в данном случае возможно еще более детальное
управление этими действиями. Общее правило может быть сформулировано следующим
образом: наличие небольшого количества ортогональных элементов, которые могут
комбинироваться различными способами, позволяет создать небольшую простую и
элегантную систему.
У большинства
долгоживущих структур данных, используемых операционной системой, есть имя или
идентификатор, по которому к ним можно обращаться. Среди очевидных примеров
можно назвать регистрационные имена, имена файлов, устройств, идентификаторов
процессов и т. д. Способ создания и использования этих имен представляет собой
важный вопрос при проектировании и реализации системы.
Имена, создаваемые для
использования их людьми, представляют собой символьные строки формата ASCII или
Unicode и, как правило, являются иерархическими. Так, иерархия отчетливо видна
на примере путей файлов, например, путь /usr/ast/books/mos2/chap-12 состоит из
имен каталогов, поиск которых следует начинать в корневом каталоге. Адреса URL
также являются иерархическими. Например, URL www.cs.vu.nl/~ast/ указывает на
определенную машину (www) определенного факультета (cs) определенного
университета (vu) определенной страны (nl). Участок URL после косой черты
обозначает определенный файл на указанной машине, в данном случае по умолчанию
это файл www/index.html в домашнем каталоге пользователя ast. Обратите
внимание, что URL (а также адреса DNS вообще, включая адреса электронной почты)
пишутся «задом наперед», начинаясь с нижнего уровня дерева, в отличие от имен
файлов, начинающихся с вершины дерева. На это можно взглянуть и по-другому,
если положить дерево горизонтально. При этом в одном случае дерево будет
начинаться слева и расти направо, а в другом случае, наоборот, будет начинаться
справа и расти влево.
Часто используется
двухуровневое именование: внешнее и внутреннее. Например, к файлам всегда можно
обратиться по имени, представляющему собой символьную строку. Кроме этого,
почти всегда существует внутреннее имя, используемое системой. В операционной
системе UNIX реальным именем файла является номер его i-узла. Имя в формате
ASCII вообще не используется внутри системы. В действительности это имя даже не
является уникальным, так как на файл может указывать несколько ссылок. А в
операционной системе Windows 2000 в качестве внутреннего имени используется
индекс файла в таблице MFT. Работа каталога заключается в преобразовании
внешних имен во внутренние.
Во многих случаях (таких
как приведенный выше пример с именем файла) внутреннее имя файла представляет
собой уникальное целое число, служащее индексом в таблице ядра. Другие примеры
имен-индексов: дескрипторы файлов в системе UNIX и дескрипторы объектов в
Windows 2000. Обратите внимание, что ни у одного из данных примеров имен нет
внешнего представления. Они предназначены исключительно для внутреннего
использования системой и работающими процессами. В целом использование для
временных имен табличных индексов, не сохраняющихся после перезагрузки системы,
является удачным замыслом.
Время связывания
Как мы видели, для
обращения к объектам в операционных системах используются различные типы имен.
Иногда преобразование имени в объект является фиксированным, а иногда нет. В
последнем случае может быть важным, когда имя связывается с объектом. Вообще
говоря, раннее связывание проще, но не обладает гибкостью, тогда как позднее
связывание сложнее, зато часто является более гибким.
Чтобы внести ясность в
понятие времени связывания, давайте рассмотрим некоторые примеры из реального
мира. Примером раннего связывания может быть практика некоторых колледжей,
позволяющих родителям зачислять своего ребенка в колледж с момента рождения и
вносить плату за его обучение заранее. Когда спустя 18 лет студент приходит в
колледж, его обучение уже полностью оплачено, независимо от стоимости обучения
на данный момент.
В промышленности ранним
связыванием является заказ деталей заранее. Напротив, производство продукта
точно в срок требует от поставщиков способности предоставлять требуемые детали
прямо на месте, без предварительного заказа. Такая схема представляет собой
пример позднего связывания.
Языками программирования
часто поддерживаются различные виды связывания для переменных. Глобальные
переменные связывает с конкретным виртуальным адресом компилятор. Это пример
раннего связывания. Локальным переменным процедуры виртуальные адреса
назначаются (в стеке) во время выполнения процедуры. Это пример промежуточного
связывания. Переменным, хранящимся в куче (память для которых выделяется при
помощи процедуры malloc в программах на языке С или процедуры new в программах
на языке Java), виртуальный адрес назначается только на время их фактического
использования. Это пример позднего связывания.
Для большей части
структур данных в операционных системах чаще применяется раннее связывание, но
иногда для гибкости используется позднее связывание. К этому вопросу имеет
отношение выделение памяти. В ранних многозадачных системах из-за отсутствия
аппаратной перенастройки адресов программу приходилось загружать по определенному
адресу памяти и настраивать ее на работу по этому адресу. Если эта программа
когда-либо выгружалась на диск, ее нужно было потом загрузить в те же адреса
памяти, в противном случае она не могла работать. Напротив, виртуальная память
с постраничной подкачкой представляет собой пример позднего связывания.
Фактический физический адрес, соответствующий данному виртуальному адресу,
неизвестен до тех пор, пока страница не будет физически перенесена в память.
Другим примером позднего
связывания является размещение окна в графическом интерфейсе пользователя. В
отличие от старых графических систем, в которых программист должен был
указывать абсолютные экранные координаты для всех изображений, в современных
графических интерфейсах пользователя программное обеспечение использует
координаты относительно исходного окна. Такие координаты неизвестны до тех пор,
пока это окно не будет выведено на экран, и даже могут быть со временем
изменены. Статические и динамические структуры
Разработчики операционных
систем постоянно вынуждены выбирать между статическими и динамическими
структурами данных. Статические структуры всегда проще для понимания, легче для
программирования и быстрее в использовании. Динамические структуры обладают
большей гибкостью. Очевидный пример – таблица процессов. В ранних системах для
каждого процесса просто выделялся фиксированный массив структур. Если таблица
процесса состояла из 256 элементов, тогда в любой момент могло существовать не
более 256 процессов. Попытка создания 257-го процесса заканчивалась неудачей по
причине отсутствия места в таблице. Аналогичные соображения были справедливы
для таблицы открытых файлов (как для каждого пользователя в отдельности, так и
для системы в целом) и различных других таблиц ядра.
Альтернативная стратегия
заключается в создании таблицы процессов в виде связного списка мини-таблиц,
начиная с одной-единственной мини-таблицы. Когда эта таблица заполняется, в
глобальном пуле выделяется память под следующую таблицу, которая связывается с
первой таблицей. Таким образом, таблица процесса не переполнится, пока не
закончится вся память у ядра.
Альтернативный метод
заключается в использовании таблицы фиксированного размера, но с выделением,
когда эта таблица заполнится, новой таблицы фиксированного размера, например, в
два раза большей. При этом текущие записи копируются из старой таблицы в новую,
а память, которая была занята старой таблицей, возвращается в пул. Таким
образом, таблица всегда остается непрерывной, а не связной. Недостаток этого
подхода состоит в том, что требуется определенное управление памятью, кроме
того, адрес таблицы будет переменным вместо константы.
То же самое относится к
стекам ядра. Когда поток переключается в режим ядра или когда запускается поток
в режиме ядра, этому потоку требуется стек в адресном пространстве ядра. Для
потоков пользователя стек можно инициализировать так, чтобы он рос вниз от
вершины виртуального адресного пространства. При этом его размер можно заранее
не указывать. Для потоков ядра размер стека должен быть указан заранее, так как
стек занимает часть виртуального адресного пространства ядра, кроме того,
стеков может быть несколько. Вопрос заключается в следующем: сколько памяти
следует выделить для каждого стека? Преимущества и недостатки различных
подходов здесь примерно такие же, как и в случае с таблицей процессов.
Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 |