Основные функции операционных систем

История появления

Barron: “Я не знаю, что это такое, но всегда узнаю ее, если увижу”.

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

- появление языков высокого уровня;

- появление первых операционных систем;

- появление сетей вычислительных машин.

Основные функции операционных систем

Операционная система (ОС) должна выполнять следующие функции:

- обеспечивать загрузку пользовательских программ и их выполнение (за исключением операционных систем, прошиваемых в ПЗУ);

- обеспечивать управление памятью. Эта функция обеспечивает получение программой памяти и управление системными ресурсами;

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

- предоставлять стандартизированный доступ к различным периферийным устройствам, таким как терминалы, печатающие устройства и др.

- предоставлять некоторый пользовательский интерфейс. Некоторые ОС в этом случае ограничиваются только предоставлением командной строки, другие – на 90% обеспечивают интерфейсную подсистему. Встраиваемые системы часто не имеют пользовательского интерфейса.

В процессе развития вычислительных систем возникали новые задачи, часть из которых начали реализовывать в рамках ОС. К ним относятся:

- параллельное или псевдопараллельное выполнение нескольких задач;

- организацию взаимодействия задач друг с другом;

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

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

Семейства операционных систем

Часто можно проследить преемственность между разными ОС, разработанными зачастую разными фирмами. Можно выделить, например:

- системы для больших компьютеров фирмы IBM – OS/390, z/OS и IBM VM;

- семейство Unix-систем (Unix, Solaris, Linux и др.);

- семейство потомков CP/M (MS DOS, семейство Win32 и др.).

Выбор операционной системы

Выбор ОС часто представляет нетривиальную задачу. Например, управление промышленным оборудованием в реальном масштабе времени предполагает использование ОС реального времени и некоторых ОС общего назначения (как правило, Unix-подобных). Если требуется высокая надежность и производительность, например, при создании серверов больших баз данных, то это отсекает системы класса ДОС и Windows (из-за низкой надежности). Если решаются задачи автоматизации конторской деятельности, то это предоставляет широкий выбор между ОС разных типов (ДОС, MS Windows и др.). Вообще, замечание, что такая-то ОС лучше такой-то, является бессмысленной, так как у каждого семейства используемых ОС есть своя область применения, где оно входит в число лучших или наиболее используемых.

Открытые системы

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

Представление данных в вычислительных системах

Представление чисел

Числа в машине (подразумевается цифровая вычислительная машина) хранятся в форме числа с фиксированной точкой (к ним относятся и целые числа) и числа с плавающей точкой (они представляются в форме мантиссы и порядка). Разрядность этих данных, как правило, кратна 8 – 8, 16, 32, 64 и т.д. Скорость выполнения операций с цифровыми данными принято давать в миллионах условных операций в секунду, например, Mflops (Million Floating Operations Per Second).

Представление изображений

Все форматы представления изображений можно разделить на растровые и векторные.

В векторном формате изображение разделяется на примитивы – прямые линии, многоугольники, окружности и их сегменты, параметрические кривые, залитые определенным цветом и стилем области, набранные определенным шрифтом отрывки текста и др. Для пересекающихся примитивов задается порядок, в котором один из них перекрывает другой. Некоторые форматы, например, PostScript, позволяют задавать собственные примитивы. Такие форматы содержат собственный язык программирования, с помощью которого можно делать разные действия. Каждый примитив описывается своими геометрическими координатами. Точность их описания может быть разной. Координаты примитивов могут быть двух- и трехмерными, как и сами примитивы. В качестве примера двухмерных форматов могут выступать PostScript (формат масштабируемой печати), PDF (Portable Document Format), WMF (Windows MetaFile), PCL (Printer Control Language – поддерживается большинством современных принтеров). Примером векторного представления движущихся изображений является MacroMedia Flash. Преобразование, например, простой фотографии в векторный формат является непростой и далеко не однозначной задачей. Поэтому не всегда имеет смысл такое преобразование. Одним из основных достоинств данного формата является его компактность.

В растровом формате изображение представляется матрицей точек (пикселов – PICture ELement). Сама матрица называется растром. Для каждого пиксела определяется его яркость и цвет. Размер матрицы называется разрешением растрового изображения. Для печатающего устройства обычно задается количество точек (пикселов) на дюйм (DPI – Dots Per Inch). Для черно-белой печати обычно достаточно (300-600) DPI. Для цветной печати с высоким качеством используют разрешения вплоть до 2400 DPI. Вторым параметром растрового изображения является разрядность одного пиксела, которую называют цветовой глубиной. Для черно-белых картинок – это один бит. В цветных изображениях пиксел разбивается на три или четыре составляющих, соответствующих разным цветам спектра. При этом цветовая глубина достигает 48 (3*16) или 64 (4*16) бит. Яркостный диапазон современных мониторов не превышает 256 градаций на цвет, то есть при выводе на монитор можно ограничиться цветовой глубиной 24 (3*8). Наиболее широко используемые модели – это RGB (Red, Green, Blue), CMY (Cyan, Magenta, Yellow), CMYG (Cyan, Magenta, Yellow, Gray). RGB используется в цветных кинескопах и видеоадаптерах, CMYG – в цветной полиграфии. В различных графических форматах используется разный способ хранения пикселов. Два основных подхода – хранить числа, соответствующие пикселам, или хранить изображение в битовых плоскостях – вначале младшие биты, затем вторые, третьи и т.д. Обычно растровое изображение снабжается заголовком, в котором указывается разрешение, глубина цвета и, нередко, цветовая модель. Наиболее используемые форматы – BMP, PCX. Также используются упакованные форматы – JPEG, TIFF, GIFF и др.

Представление звуков

Существует два подхода к хранению звуковых файлов – это MIDI (Music Interface Digital Instrument) и подобные, и оцифрованный звук.

В формате MIDI звук генерируется синтезатором, который порождает звуки различного тембра, высоты, длительности и громкости. Тембры, как правило, соответствуют тембрам распостраненных музыкальных инструментов. Вместо звука в данном случае хранится последовательность команд синтезатора. Используя данный подход, можно хранить фонемы человеческого языка и воспроизводить речь. Достоинством данного формата является его компактность, а недостатком – зависимость качества звучания от качества синтезатора, реализованного в конкретной звуковой карте.

Оцифрованный звук является результатом аналого-цифрового преобразования реального звука. Его характеристиками являются частота дискретизации, разрешение АЦП и количество каналов. Например, в формате цифрового звука лазерных дисков есть два канала (стереозвук), частота дискретизации 44,1 КГц, количество бит АЦП на канал – 16. Для записи речи вполне хватает частоты дискретизации 22 КГц, а просто для разборчивости произносимых фраз без узнавания говорящего – и 10 КГц. Поскольку данные в этом формате занимают много памяти (в формате лазерного аудиодиска одна минута – это примерно 9 МБт данных), то используются упакованные данные. Наиболее применяемым в настоящее время является формат MPEG-3.

Упаковка данных

Часто данные имеют значительный объем, поэтому их хранение и передача требует значительных ресурсов. Одним из способов решения этой проблемы является упаковка данных.

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

Одним из первых методов упаковки является азбука Морзе (1844г.). В ней наиболее использующиеся буквы кодировались наиболее короткими посылками.

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

Коды Хаффмана и Шеннона-Фано устраняют автокорреляции, соответствующие неравномерности встречаемых символов, но сохраняют без изменений часто встречающиеся последовательности символов, а они ответственны за значительную часть избыточности текстов на естественных и синтетических языках. Для упаковки данных такого рода в конце 1970-х годов Лемпелем и Зиффом было предложено семейство алгоритмов, наиболее известные из которых – LZ77 и LZW. Все эти алгоритмы сводятся к поиску в потоке повторяющихся последовательностей и замене этих последовательностей на их номер в динамически формируемом словаре. Различие этих алгоритмов состоит в способах кодирования номера и формировании словаря. Номер последовательности в словаре должен содержать больше битов, чем символы исходного потока хотя бы из-за того, чтобы его можно было отличить от символа, поэтому алгоритмы Лемпеля-Зиффа предполагают дальнейшее перекодирование преобразованного потока кодом Хаффмана. Большинство современных архиваторов, таких, как PkZip, GNU Zip, RAR, основаны на вариациях и аналогах алгоритмов Лемпеля-Зиффа.

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

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

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

Для упаковки данных, полученных путем оцифровки реальных сигналов, например, видео и звука, эти алгоритмы не подходят совершенно. Это связано с тем, что реальный сигнал всегда сопровождается тепловым (белым) шумом. Этот не имеющий автокорреляций шум искажает присутствующие во входном потоке автокорреляции, поэтому точные алгоритмы с зашумленным сигналом справиться не могут. Поэтому упаковка аудиозаписи или цифровой фотографии алгоритмами класса Zip или RAR не даст большого результата (а на текстовых данных эти алгоритмы часто дают выигрыш в 10 и более раз). Идея алгоритмов, пригодных для сжатия зашумленных сигналов, пришла из области работы цифровых фильтров-шумоподавителей. Эти фильтры осуществляют над сигналом преобразование Фурье и удаляют из полученного спектрального образа самые слабые частоты, которые ниже порога подавления. Сигнал при этом искажается и наиболее страдают составляющие равномерно распределенного по спектру шума, что и требуется. Алгоритмы JFIF (он находится в основе формата JPEG), MPEG, MP3 и другие алгоритмы тоже начинают с выполнения над входным потоком преобразования Фурье. Далее алгоритм JFIF удаляет из полученного спектра фиксированное количество частот, стремясь отобрать самые слабые. Количество частот, которые надо выкинуть, определяется параметром настройки упаковщика. У JFIF этот параметр называется коэффициентом упаковки, у MP3 – битрейтом. Профильтрованный сигнал заведомо содержит автокорреляции и поэтому легко подвергается упаковке. Благодаря этому все эти алгоритмы обеспечивают гарантированный уровень упаковки. Все эти алгоритмы относятся к классу необратимых, так как восстановить по нему исходный сигнал невозможно. При разумном выборе уровня упаковки восстановленное изображение или звук практически неотличимо от оригинала, но если это восстановленное изображение или звук еще раз пропустить через упаковку, то будет заметно искажение исходного потока данных. Поэтому иногда необратимые алгоритмы упаковки предлагается использовать для защиты авторских прав: потребитель получает упакованный файл, а исходный остается у автора.

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

Введение в криптографию

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

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

Практически все методы криптографии сводятся к преобразованию данных в набор из конечного количества символов и осуществлению над этими символами двух основных операций: подстановки и перестановки. Подстановка состоит в замене одних символов на другие. Перестановка состоит в изменении порядка символов. В качестве символов при этом могут выступать различные элементы сообщения – так, при шифровании сообщений на естественных языках подстановке и перестановке могут подвергаться как отдельные буквы, так и слова или даже целые предложения (как, например, в аллегорических изложениях магических и священных текстов). В современных алгоритмах этим операциям чаще всего подвергаются блоки последовательных битов. Некоторые методики можно описать как осуществление операции подстановки над полным сообщением. Подстановки и перестановки производятся по определенным правилам. При этом надежда возлагается на то, что эти правила и/или используемые в них параметры известны только автору и получателю шифрованного сообщения и неизвестны посторонним лицам. В докомпьютерную эру старались засекретить обе составляющие процесса шифрования. Сейчас для шифрования, как правило, используют стандартные алгоритмы, секретность же сообщения достигается путем засекречивания используемого алгоритмом параметра, ключа (key). Прочтение секретного сообщения посторонним лицом, теоретически, может быть осуществлено двумя способами: похищением ключевого значения либо его угадыванием путем анализа перехваченной шифровки. Если первое мероприятие может быть предотвращено только физической и организационной защитой, то возможность второго определяется используемым алгоритмом. Ниже мы будем называть процесс анализа шифровки взломом шифра, а человека, осуществляющего этот процесс, – взломщиком. По-научному эта деятельность называется более нейтрально – криптоанализ. К примеру, сообщение на естественном языке, зашифрованное подстановкой отдельных букв, уязвимо для частотного анализа: основываясь на том факте, что различные буквы встречаются в текстах с разной частотой, взломщик легко – и с весьма высокой достоверностью – может восстановить таблицу подстановки. Существуют и другие примеры неудачных алгоритмов, которые сохраняют в неприкосновенности те или иные присутствовавшие в сообщении автокорреляции – каждый такой параметр можно использовать как основу для восстановления текста сообщения или обнаружения ключа.

Устойчивость шифра к поиску автокорреляций в сообщении называется криптостойкостью алгоритма. Даже при использовании удачных в этом смысле алгоритмов, если взломщик знает, что исходные (нешифрованные) данные удовлетворяют тому или иному требованию, например, содержат определенное слово или снабжены избыточным кодом, он может произвести полный перебор пространства ключей: перебирать все значения ключа, допускаемые алгоритмом, пока не будет получено удовлетворяющее требованию сообщение. При использовании ключей достаточно большой разрядности такая атака оказывается чрезмерно дорогой, однако прогресс вычислительной техники постоянно сдвигает границу "достаточности" все дальше и дальше. Так, сеть распределенных вычислений Bovine в 1998 году взломала сообщение, зашифрованное алгоритмом DES с 56-разрядным ключом за 56 часов работы. Простым и эффективным способом борьбы с такой атакой является расширение пространства ключей. Увеличение ключа на один бит приводит к увеличению пространства вдвое – таким образом, линейный рост размера ключа обеспечивает экспоненциальный рост стоимости перебора. Некоторые алгоритмы шифрования не зависят от разрядности используемого ключа – в этом случае расширение достигается очевидным способом. Если же в алгоритме присутствует зависимость от разрядности, расширить пространство можно, всего лишь применив к сообщению несколько разных преобразований, в том числе и одним алгоритмом, но с разными ключами. Еще один способ существенно усложнить работу взломщику – это упаковка сообщения перед шифрованием и/или дополнение его случайными битами. Важно подчеркнуть, впрочем, что количество двоичных разрядов ключа является лишь оценкой объема пространства ключей сверху, и во многих ситуациях эта оценка завышена. Некоторые алгоритмы в силу своей природы могут использовать только ключи, удовлетворяющие определенному условию – например, RSA использует простые числа. Это резко сужает объем работы по перебору, поэтому для обеспечения сопоставимой криптостойкости разрядность ключа RSA должна быть намного больше, чем у алгоритмов, допускающих произвольные ключи. Низкая криптостойкость может быть обусловлена. не только алгоритмом шифрования, но и процедурой выбора ключа: если ключ может принимать любые двоичные значения заданной разрядности, но реально для его выбора используется страдающий неоднородностью генератор псевдослучайных чисел, мы можем значительно сократить объем пространства, которое реально должен будет перебрать взломщик наших сообщений. Еще хуже ситуация, когда в качестве ключа используются легко запоминаемые слова естественного языка: в этом случае реальный объем пространства ключей даже довольно большой разрядности может измеряться всего лишь несколькими тысячами различных значений.

Современные алгоритмы шифрования делятся на два основных класса: с секретным и с публичным ключом.

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

Основные функции операционных систем - student2.ru

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

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

В системах цифровой связи широкое применение получили блочные алгоритмы, выполняющие над блоками данных фиксированной длины последовательности – иногда довольно сложные – перестановок, подстановок и других операций, чаще всего двоичных сложений данных с ключом по какому-либо модулю. В операциях используются компоненты ключевого слова относительно небольшой разрядности. Например, широко применяемый блочный алгоритм DES шифрует 64-битные блоки данных 56-битным ключом. Для современной вычислительной техники полный перебор 56-битного пространства возможен, поэтому сейчас все большее распространение получают алгоритмы с большей разрядностью ключа – Blowfish, IDEAL и др.

Шифры с открытым ключом называются также двухключевыми. Если в алгоритмах со скрытым ключом для кодирования и декодирования сообщений используется один и тот же ключ, то здесь используются два ключа: публичный и приватный. Для прочтения сообщения, закодированного публичным ключом, необходим приватный, и наоборот. Помимо обычных соображений криптостойкости, к таким алгоритмам предъявляется дополнительное требование: невозможность восстановления приватного ключа по публичному иначе как полным перебором пространства ключей. Двухключевые схемы шифрования намного сложнее в разработке, чем схемы с секретным ключом: требуется найти преобразование, не поддающееся обращению при помощи применявшегося в нем публичного ключа, но такое, чтобы с применением приватного ключа его все-таки можно было обратить. Известные криптоустойчивые схемы основаны на произведениях простых чисел большой разрядности, дискретных логарифмах и эллиптических кривых. Наиболее широкое применение получил разработанный в 1977 г. алгоритм RSA. Известные двухключевые алгоритмы требуют соответствия ключей весьма специфическим требованиям, поэтому для достижения криптостойкости, сопоставимой с блочными алгоритмами, необходимо использовать ключи намного большей разрядности. Так, снятые в 2000 году ограничения Министерства торговли США устанавливали ограничения разрядности ключа, который мог использоваться в экспортируемом за пределы США программном обеспечении: для схем с секретным ключом устанавливался предел, равный 48 битам, а для схем с открытым – 480. Использование ключей большой разрядности требует значительных вычислительных затрат, поэтому двухключевые схемы чаще всего применяются в сочетании с обычными: обладатель публичного ключа генерирует случайную последовательность битов, кодирует ее и отправляет обладателю приватного ключа. Затем эта последовательность используется в качестве секретного ключа для шифрования данных. При установлении двустороннего соединения стороны могут сначала обменяться своими публичными ключами, а затем использовать их для установления двух разных секретных ключей, используемых для шифрования данных, передаваемых в разных направлениях. Такая схема делает практичной частую смену секретных ключей: так, в протоколе SSH ключ генерируется на каждую сессию, в протоколе виртуальных приватных сетей IPSEC время жизни ключа ограничено восемью часами. Еще более широкое применение двухключевые схемы нашли в области аутентификации и электронной подписи. Электронная подпись представляет собой контрольную сумму сообщения, зашифрованную приватным ключом отправителя. Каждый обладатель соответствующего публичного ключа может проверить аутентичность подписи и целостность сообщения. Это может использоваться для проверки аутентичности как сообщения, так и самого отправителя. Использование в качестве контрольной суммы обычного CRC невозможно, потому что генерация сообщения с заданным CRC не представляет вычислительной сложности. Для применения в электронной подписи были разработаны специальные алгоритмы вычисления контрольных сумм, затрудняющие подбор сообщения с требуемой суммой.

Загрузка программ

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

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

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

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

Некоторые системы предоставляют и более крупные структурные единицы, чем процесс. Например, в системах семейства Unix существуют группы процессов, которые используются для реализации логического объединения процессов в задания (job). Ряд систем имеют также понятие сессии – совокупности всех заданий, которые пользователь запустил в рамках одного сеанса работы. Впрочем, соответствующие концепции часто плохо определены, а их смысл сильно меняется от одной ОС к другой.

В более старых системах и в старой литературе называют результат загрузки задачей, а процессами – отдельные нити управления. Однако в наиболее распространенных ныне ОС семейств Unix и Win32, принято задачу называть процессом, а процесс – нитью (tread).

Абсолютная загрузка

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

1. Система может предоставить каждому процессу свое адресное пространство. Это возможно только на процессорах, осуществляющих трансляцию виртуального адреса в физический.

2. Система может исполнять в каждый момент только один процесс. Так ведет себя СР/М, так же устроено большинство загрузочных мониторов для самодельных компьютеров. Похожим образом устроена система RT-11.

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

Начальное содержимое образа процесса формируется путем простого копирования модуля в память. В системе RT-11,например, такие файлы имеют расширение sav от saved – сохраненный.

Разделы памяти

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

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

Относительная загрузка

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

Сложность здесь в том, что если абсолютные адресные поля можно найти анализом кодов команд (деассемблированием), то значение в адресный регистр может загружаться задолго до собственно адресации, причем формирование значения регистра может происходить и по частям. На практике содействие программиста загрузчику состоит в том, что программист старается без необходимости не использовать в адресных полях и в качестве значений адресных регистров произвольные значения. Вместо этого, программист применяет ассемблерные символы, соответствующие адресам. Ассемблер при каждой ссылке на такой символ генерирует не только “заготовку” адреса в коде, но и запись в таблице перемещений (relocation table). Эта запись хранит место ссылки на такой символ в коде или данных.

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

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

Наиболее поучительна в этом отношении система RT-11, в которой существуют загружаемые модули обоих типов. Обычные программы имеют расширение sav, представляют собой абсолютные загружаемые модули и грузятся всегда с адреса 01000. Ниже этого магического адреса находятся векторы прерываний и стек программы. Сама операционная система вместе с драйверами размещается в верхних адресах памяти. Естественно, нельзя загрузить одновременно два sav-файла.

Однако, если обязательно нужно исполнять одновременно две программы, можно собрать вторую из них в виде относительного модуля: файла с расширением rel. Такая программа будет загружаться в верхние адреса памяти, каждый раз разные, в зависимости от конфигурации ядра системы, количества загруженных драйверов устройств и других геl-модулей.

Базовая адресация

Если мы полагаемся на содействие программиста, можно пойти дальше: мы объявляем один или несколько регистров процессора базовыми (несколько регистров могут использоваться для адресации различных сегментов программы, например, один – для кода, другой – для статических данных, третий – для стека) и договариваемся, что значения этих регистров программист принимает как данность и никогда сам не модифицирует, зато все адреса в программе он вычисляет на основе значений этих регистров. В этом случае для перемещения программы нам нужно только изменить значения базовых регистров, и программа даже не узнает, что загружена с другого адреса. Статически инициализованными указателями в этом случае пользоваться либо невозможно, либо необходимо всегда прибавлять к ним значения базовых регистров. Именно так происходит загрузка COM-файлов в системе MS DOS. Система выделяет свободную память, настраивает для программы базовые регистры DS и CS, которые называются сегментными, и передает управление на стартовый адрес. Ничего больше делать не надо.

Позиционно-независимый код

Третий способ – это относительная адресация, когда адрес получается сложением адресного поля команды и адреса самой этой команды – значения счетчика команд. Код, в котором используется только такая адресация, можно загружать с любого адреса без всякой перенастройки. Такой код называется позиционно-независшлым (position-independent). Позиционно-независимые программы очень удобны для загрузки, но, к сожалению, при их написании следует соблюдать довольно жесткие ограничения, накладываемые на используемые в программе методы адресации. Например, нельзя пользоваться статически инициализованными переменными указательного типа. Возникают сложности при сборке программы из нескольких модулей. К тому же, на многих процессорах, например, на Intel 8080/8085 или многих современных RISC-процессорах, описанная выше реализация позиционно-независимого кода вообще невозможна, так как эти процессоры не поддерживают соответствующий режим адресации для данных. На процессорах гарвардской архитектуры адресовать данные относительно счетчика команд вообще невозможно – команды находятся в другом адресном пространстве. Поэтому такой стиль программирования используют только в особых случаях.

Оверлеи (перекрытия)

Еще более интересный способ загрузки программы

Наши рекомендации