Файл: А. В. Гордеев А. Ю. Молчанов системное программное обеспечение электронный вариант книги издательства Питер СанктПетербург Челябинск юургу каф. Автоматика и управление 2002 2 Предисловие Настоящий учебник.pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 12.01.2024
Просмотров: 1037
Скачиваний: 1
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
257
«Старый» UNIX – многозадачная ОС, где задачами являются процессы (а не тре- ды), которые сообщаются через потоки (pipes) и разделяемую память. Оба эти ме- ханизма используют файловую систему, а её поведение – непредсказуемо.
Комбинация приоритетов тредов и разделения ресурсов между ними приводит к другому явлению – классической проблеме инверсии приоритетов. Это можно проиллюстрировать на примере, когда есть как минимум три треда. Когда тред низшего приоритета захватил ресурс, разделяемый с тредом высшего приоритета, и начал выполняться поток среднего приоритета, выполнение треда высшего при- оритета будет приостановлено, пока не освободится ресурс и не отработает тред среднего приоритета. В этой ситуации время, необходимое для завершения треда высшего приоритета, зависит от нижних приоритетных уровней, – это и есть ин- версия приоритетов. Ясно, что в такой ситуации трудно выдержать ограничение на время исполнения.
Чтобы устранить такие инверсии, ОСРВ должна допускать наследование при- оритета, то есть повышение уровня приоритета треда до уровня треда, который его вызывает. Наследование означает, что блокирующий ресурс тред наследует при- оритет треда, который он блокирует (разумеется, это справедливо лишь в том слу- чае, если блокируемый тред имеет более высокий приоритет).
Иногда можно услышать утверждение, что в грамотно спроектированной сис- теме такая проблема не возникает. В случае сложных систем с этим нельзя согла- ситься. Единственный способ решения этой проблемы состоит в увеличении при- оритета треда «вручную» прежде, чем ресурс окажется заблокированным. Разуме- ется, это возможно в случае, когда два треда разных приоритетов претендуют на один ресурс. В общем случае решения не существует.
Синхронизация процессов и задач
Требование 4. ОС должна обеспечивать мощные, надежные и удобные меха- низмы синхронизации задач. Так как задачи разделяют данные (ресурсы) и должны сообщаться друг с другом, представляется логичным, что должны существовать механизмы блокирования и коммуникации. Необходимы механизмы, гарантиро- ванно предоставляющие возможность параллельно выполняющимся задачам и
258
процессам оперативно обмениваться сообщениями и синхросигналами. Эти сис- темные механизмы должны быть всегда доступны процессам, требующим реально- го времени. Следовательно, системные ресурсы для их функционирования должны быть распределены заранее.
Предсказуемость
Требование 5. Поведение ОС должно быть известно и достаточно точно про- гнозируемо.
Времена выполнения системных вызовов и временные характеристики пове- дения системы в различных обстоятельствах должны быть известны разработчику.
Поэтому создатель ОСРВ должен приводить следующие характеристики:
♦ латентную задержку прерывания (то есть время от момента прерывания до момента запуска задачи): она должна быть предсказуема и согласована с требова- ниями приложения. Эта величина зависит от числа одновременно «висящих» пре- рываний;
♦ максимальное время выполнения каждого системного вызова. Оно должно быть предсказуемо и не зависимо от числа объектов в системе;
♦ максимальное время маскирования прерываний драйверами и ОС.
Принципы построения интерфейсов операционных систем
Напомним, что ОС всегда выступает как интерфейс между аппаратурой ком- пьютера и пользователем с его задачами. Под интерфейсами операционных систем здесь и далее следует понимать специальные интерфейсы системного прикладного программирования, предназначенные для выполнения следующих задач:
♦ Управление процессами, которое включает в себя следующий набор основ- ных функций:
• запуск, приостанов и снятие задачи с выполнения;
• задание или изменение приоритета задачи;
• взаимодействие задач между собой (механизмы сигналов, семафорные при- митивы, очереди, конвейеры, почтовые ящики);
• RPC (remote procedure call) – удаленный вызов подпрограмм.
259
♦ Управление памятью:
• запрос на выделение блока памяти;
• освобождение памяти;
• изменение параметров блока памяти (например, память может быть забло- кирована процессом либо предоставлена в общий доступ);
• отображение файлов на память (имеется не во всех системах).
♦ Управление вводом/выводом:
• запрос на управление виртуальными устройствами (напомним, что управ- ление вводом/выводом является привилегированной функцией самой ОС, и ника- кая из пользовательских задач не должна иметь возможности непосредственно управлять устройствами);
• файловые операции (запросы к системе управления файлами на создание,
изменение и удаление данных, организованных в файлы).
Здесь мы перечислили основные наборы функций, которые выполняются ОС
по соответствующим запросам от задач. Что касается пользовательского интерфей- са операционной системы, то он реализуется с помощью специальных программ- ных модулей, которые принимают его команды на соответствующем языке (воз- можно, с использованием графического интерфейса) и транслируют их в обычные вызовы в соответствии с основным интерфейсом системы. Обычно эти модули на- зывают интерпретатором команд. Так, например, функции такого интерпретатора в
MS-DOS выполняет модуль COMMAND.COM. Получив от пользователя команду,
такой модуль после лексического и синтаксического анализа либо сам выполняет действие, либо, что случается чаще, обращается к другим модулям ОС, используя механизм API. Надо заметить, что в последние годы большую популярность полу- чили графические интерфейсы (GUI), в которых задействованы соответствующие манипуляторы типа «мышь» или «трекбол»
1
. Указание курсором на объекты и щелчок (клик) или двойной щелчок по соответствующим клавишам приводит к ка- ким-либо действиям – запуску программы, ассоциированной с указываемым объ-
1
Trackball – в переносных компьютерах очень часто используется для управления перемещением курсора специаль- ный шарик, который размещается рядом с клавиатурой и прокручивается пальцами.
260
ектом, выбору и/или активизации пунктов меню и т. д. Можно сказать, что такая интерфейсная подсистема транслирует «команды» пользователя в обращения к ОС.
Поясним также, что управление GUI – частный случай задачи управления вво- дом/выводом, не являющийся частью ядра операционной системы, хотя в ряде слу- чаев разработчики ОС относят функции GUI к основному системному API.
Следует отметить, что имеются два основных подхода к управлению задача- ми. Так, в одних системах порождаемая задача наследует все ресурсы задачи–ро- дителя, тогда как в других системах существуют равноправные отношения, и при порождении нового процесса ресурсы для него запрашиваются у операционной системы.
Обращения к операционной системе, в соответствии с имеющимся API, может осуществляться как посредством вызова подпрограммы с передачей ей необходи- мых параметров, так и через механизм программных прерываний. Выбор метода реализации вызовов функций API должен определяться архитектурой платформы.
Так, например, в операционной системе MS-DOS, которая разрабатывалась для однозадачного режима (поскольку процессор i8086 не поддерживал мульти- программирование), использовался механизм программных прерываний. При этом основной набор функций API был доступен через точку входа обработчика int 21h.
В более сложных системах имеется не одна точка входа, а множество – по ко- личеству функций API. Так, в большинстве операционных систем используется ме- тод вызова подпрограмм. В этом случае вызов сначала передается в модуль API
(например, это библиотека времени выполнения
1
), который и перенаправляет вызов соответствующим обработчикам программных прерываний, входящим в состав операционной системы. Использование механизма прерываний вызвано, главным образом, тем, что при этом процессор переводится в режим супервизора.
1
RTL (run time library) – библиотека времени выполнения; она включает в себя те стандартные подпрограммы, кото- рые система программирования подставляет на этапе компиляции. В общем случае RTL включает в себя не только модули из системы программирования, но и модули самой ОС.
261
Интерфейс прикладного программирования
Прежде всего необходимо однозначно разделить общий термин API (applica- tion program interface, интерфейс прикладного программирования) на следующие направления:
♦ API как интерфейс высокого уровня, принадлежащий к библиотекам RTL;
♦ API прикладных и системных программ, входящих в поставку операцион- ной системы;
♦ прочие API.
Интерфейс прикладного программирования, как это и следует из названия,
предназначен для использования прикладными программами системных ресурсов
ОС и реализуемых ею функций. API описывает совокупность функций и процедур,
принадлежащих ядру или надстройкам ОС.
Итак, API представляет собой набор функций, предоставляемых системой программирования разработчику прикладной программы и ориентированных на организацию взаимодействия результирующей прикладной программы с целевой
вычислительной системой. Целевая вычислительная система представляет собой совокупность программных и аппаратных средств, в окружении которых выполня- ется результирующая программа. Сама результирующая программа порождается системой программирования на основании кода исходной программы, созданного разработчиком, а также объектных модулей и библиотек, входящих в состав систе- мы программирования.
В принципе API используется не только прикладными, но и многими систем- ными программами, как в составе ОС, так и в составе системы программирования.
Но дальше речь пойдет только о функциях API с точки зрения разработчика прикладной программы. Для системной программы существуют некоторые допол- нительные ограничения на возможные реализации API.
Функции API позволяют разработчику строить результирующую прикладную программу так, чтобы использовать средства целевой вычислительной системы для выполнения типовых операций. При этом разработчик программы избавлен от не- обходимости создавать исходный код для выполнения этих операций.
262
Программный интерфейс API включает в себя не только сами функции, но и соглашения об их использовании, которые регламентируются операционной сис- темой (ОС), архитектурой целевой вычислительной системы и системой програм- мирования.
Существует несколько вариантов реализации API:
♦ реализация на уровне ОС;
♦ реализация на уровне системы программирования;
♦ реализация на уровне внешней библиотеки процедур и функций.
Система программирования в каждом из этих вариантов предоставляет разра- ботчику средства для подключения функций API к исходному коду программы и организации их вызовов. Объектный код функций API подключается к результи- рующей программе компоновщиком при необходимости.
Возможности API можно оценивать со следующих позиций:
♦ эффективность выполнения функций API – включает в себя скорость вы- полнения функций и объём вычислительных ресурсов, потребных для их выполне- ния;
♦ широта предоставляемых возможностей;
♦ зависимость прикладной программы от архитектуры целевой вычислитель- ной системы.
В идеале хотелось бы иметь набор функций API, выполняющихся с наивыс- шей эффективностью, предоставляющих пользователю все возможности совре- менных ОС и имеющих минимальную зависимость от архитектуры вычислитель- ной системы (ещё лучше – лишённых такой зависимости).
Добиться наивысшей эффективности выполнения функций API практически трудно по тем же причинам, по которым невозможно добиться наивысшей эффек- тивности выполнения для любой результирующей программы. Поэтому об эффек- тивности API можно говорить только в сравнении его характеристик с другим API.
Что касается двух других показателей, то в принципе нет никаких технических ограничений на их реализацию. Однако существуют организационные проблемы и узкие корпоративные интересы, тормозящие создание такого рода библиотек.
263
Реализация функций API на уровне ОС
При реализации функций API на уровне ОС за их выполнение ответственность несет ОС. Объектный код, выполняющий функции, либо непосредственно входит в состав ОС (или даже ядра ОС), либо поставляется в составе динамически загру- жаемых библиотек, разработанных для данной ОС. Система программирования от- ветственна только за то, чтобы организовать интерфейс для вызова этого кода.
В таком варианте результирующая программа обращается непосредственно к
ОС. Поэтому достигается наибольшая эффективность выполнения функций API по сравнению со всеми другими вариантами реализации API.
Недостатком организации API по такой схеме является практически полное отсутствие переносимости не только кода результирующей программы, но и кода исходной программы. Программа, созданная для одной архитектуры вычислитель- ной системы, не сможет исполняться на вычислительной системе другой архитек- туры даже после того, как её объектный код будет полностью перестроен. Чаще всего система программирования не сможет выполнить перестроение исходного кода для новой архитектуры вычислительной системы, поскольку многие функции
API, ориентированные на определённую ОС, будут в новой архитектуре просто от- сутствовать.
Таким образом, в данной схеме для переноса прикладной программы с одной целевой вычислительной системы на другую будет требоваться изменение исход- ного кода программы.
Переносимости можно было бы добиться, если унифицировать функции API в различных ОС. С учётом корпоративных интересов производителей ОС такое на- правление их развития представляется практически невозможным. В лучшем слу- чае при приложении определённых организационных усилий удаётся добиться стандартизации смыслового (семантического) наполнения основных функций API,
но не их программного интерфейса.
Хорошо известным примером API такого рода может служить набор функций,
предоставляемых пользователю со стороны ОС типа Microsoft Windows – WinAPI
(Windows API). Надо сказать, что даже внутри этого корпоративного API сущест- вует определенная несогласованность, которая несколько ограничивает переноси-
264
мость программ между различными ОС типа Windows. Еще одним примером тако- го API можно считать набор сервисных функций ОС типа MS-DOS, реализованный в виде набора подпрограмм обслуживания программных прерываний.
Реализация функций API на уровне системы программирования
Если функции API реализуются на уровне системы программирования, они предоставляются пользователю в виде библиотеки функций соответствующего языка программирования. Обычно речь идет о библиотеке времени исполнения –
RTL (run time library). Система программирования предоставляет пользователю библиотеку соответствующего языка программирования и обеспечивает подклю- чение к результирующей программе объектного кода, ответственного за выполне- ние этих функций. Очевидно, что эффективность функций API в таком варианте будет несколько ниже, чем при непосредственном обращении к функциям ОС. Так происходит, поскольку для выполнения многих функций API библиотека RTL язы- ка программирования должна всё равно выполнять обращения к функциям ОС. На- личие всех необходимых вызовов и обращений к функциям ОС в объектном коде
RTL обеспечивает система программирования.
Однако переносимость исходного кода программы в таком варианте будет са- мой высокой, поскольку синтаксис и семантика всех функций будут строго регла- ментированы в стандарте соответствующего языка программирования. Они зависят от языка и не зависят от архитектуры целевой вычислительной системы. Поэтому для выполнения прикладной программы на новой архитектуре вычислительной системы достаточно заново построить код результирующей программы с помощью соответствующей системы программирования.
Единообразное выполнение функций языка обеспечивается системой про- граммирования. При ориентации на различные архитектуры целевой вычислитель- ной системы в системе программирования могут потребоваться различные комби- нации вызовов функций ОС для выполнения одних и тех же функций исходного языка. Это должно быть учтено в коде RTL. В общем случае для каждой архитек- туры целевой вычислительной системы будет требоваться свой код RTL языка программирования. Выбор того или иного объектного кода RTL для подключения
265
к результирующей программе система программирования обеспечивает автомати- чески.
Например, рассмотрим функции динамического выделения памяти в языках С
и Pascal. В С это функции mallос, realloc и free (функции new и delete в C++), в Pas- cal – функции new и dispose. Если использовать эти функции в исходном тексте программы, то с точки зрения исходной программы они будут действовать одина- ковым образом в зависимости только от семантики исходного кода. При этом для разработчика исходной программы не имеет значения, на какую архитектуру ори- ентирована его программа. Это имеет значение для системы программирования,
которая для каждой из этих функций должна подключить к результирующей про- грамме объектный код библиотеки. Этот код будет выполнять обращение к соот- ветствующим функциям ОС. Не исключено даже, что для однотипных по смыслу функций в разных языках (например, malloc в С и new в языке Pascal выполняют схожие по смыслу действия) этот код будет выполнять схожие обращения к ОС.
Однако для различных вариантов ОС этот код будет различен даже при использо- вании одного и того же исходного языка.
Проблема, главным образом, заключается в том, что большинство языков про- граммирования предоставляют пользователю не очень широкий набор стандарти- зованных функций. Поэтому разработчик исходного кода существенно ограничен в выборе доступных функций API. Как правило, набора стандартных функций ока- зывается недостаточно для создания полноценной прикладной программы. Тогда разработчик может обратиться к функциям других библиотек, имеющихся в соста- ве системы программирования. В этом случае нет гарантии, что функции, вклю- чённые в состав данной системы программирования, но не входящие в стандарт языка программирования, будут доступны в другой системе программирования.
Особенно если она ориентирована на другую архитектуру целевой вычислительной системы. Такая ситуация уже ближе к третьему варианту реализации API.
Например, те же функции mallос, realloc и free в языке С фактически не вхо- дят в стандарт языка. Они входят в состав стандартной библиотеки, которая «де–
факто» входит во все системы программирования, построенные на основе языка С.
266
Общепринятые стандарты существует для многих часто используемых функций языка. Если же взять более специфические функции, такие как функции порожде- ния новых процессов, то для них ни в С, ни в языке Pascal не окажется общеприня- того стандарта.
1 ... 17 18 19 20 21 22 23 24 ... 37