Компоновщик (или редактор связей) предназначен для связывания между собой объектных файлов, порождаемых компилятором, а также файлов библиотек, входящих в состав системы программирования.
Объектный файл (или набор объектных файлов) не может быть исполнен до тех пор, пока все модули и секции не будут в нем увязаны между собой. Это и делает редактор связей (компоновщик). Результатом его работы является единый файл (часто называемый «исполняемым файлом»), который содержит весь текст результирующей программы на языке машинных кодов. Компоновщик может порождать сообщение об ошибке, если при попытке собрать объектные файлы в единое целое он не смог обнаружить какой-либо необходимой составляющей.
Функция компоновщика достаточно проста. Он начинает свою работу с того, что выбирает из первого объектного модуля программную секцию и присваивает ей начальный адрес. Программные секции остальных объектных модулей получают адреса относительно начального адреса в порядке следования. При этом может выполняться также функция выравнивания начальных адресов программных секций. Одновременно с объединением текстов программных секций объединяются секции данных, таблицы идентификаторов и внешних имен. Разрешаются межсекционные ссылки.
Существуют в технической литературе примеры, когда компоновщик называли загрузчиком. C точки зрения автора это принципиально неправильно. Функции компоновщика и загрузчика существенно различаются. B современных системах программирования загрузчик, как правило, отсутствует, его функции выполняет OC.
Процедура разрешения ссылок сводится к вычислению значений адресных констант процедур, функций и переменных с учетом перемещений секций относительно начала собираемого программного модуля. Если при этом обнаруживаются ссылки к внешним переменным, отсутствующим в списке объектных модулей, редактор связей организует их поиск в библиотеках, доступных в системе программирования. Если же и в библиотеке необходимую составляющую найти не удается, формируется сообщение об ошибке.
Обычно компоновщик формирует простейший программный модуль, создаваемый как единое целое. Однако в более сложных случаях компоновщик может создавать и другие модули: программные модули с оверлейной структурой, объектные модули библиотек и модули динамически подключаемых библиотек (работа с оверлейными и динамически подключаемыми модулями в OC описана в первой части данного пособия).
Большинство объектных модулей в современных системах программирования строятся на основе так называемых относительных адресов. Компилятор, порождающий объектные файлы, а затем и компоновщик, объединяющий их в единое целое, не могут знать точно, в какой реальной области памяти компьютера будет располагаться программа в момент ее выполнения. Поэтому они работают не с реальными адресами ячеек ОЗУ, а с некоторыми относительными адресами. Такие адреса отсчитываются от некоторой условной точки, принятой за начало области памяти, занимаемой результирующей программой (обычно это точка начала первого модуля программы).
Конечно, ни одна программа не может быть исполнена в этих относительных адресах. Поэтому требуется модуль, который бы выполнял преобразование относительных адресов в реальные (абсолютные) адреса непосредственно в момент запуска программы на выполнение. Этот процесс называется трансляцией адресов и выполняет его специальный модуль, называемый загрузчиком.
B современных OC существуют сложные методы преобразования адресов, которые работают непосредственно уже во время выполнения программы. Эти методы основаны на возможностях, аппаратно заложенных в архитектуру вычислительных комплексов. Методы трансляции адресов могут быть основаны на сегментной, страничной и сегментно-страничной организации памяти (все эти методы рассмотрены в первой части данного пособия). Тогда для выполнения трансляции адресов в момент запуска программы должны быть подготовлены соответствующие системные таблицы. Эти функции целиком ложатся на модули OC, поэтому они не выполняются в системах программирования.
Еще одним модулем системы программирования, функции которого тесно связаны с выполнением программы, является отладчик.
Отладчик - это программный модуль, который позволяет выполнить основные задачи, связанные с мониторингом процесса выполнения результирующей прикладной программы. Этот процесс называется отладкой и включает в себя пошаговое выполнение результирующей программы на основе шагов по машинным командам или по операторам входного языка, выполнение результирующей программы до достижения ею одной из заданных точек останова (адресов останова), выполнение результирующей программы до наступления некоторых заданных условий, связанных с данными и адресами, обрабатываемыми этой программой, просмотр содержимого областей памяти, занятых командами или данными результирующей программы.
Первоначально отладчики представляли собой отдельные программные модули, которые могли обрабатывать результирующую программу в терминах языка машинных команд. Их возможности в основном сводились к моделированию выполнения результирующих программ в архитектуре соответствующей вычислительной системы. Выполнение могло идти непрерывно либо по шагам.
Дальнейшее развитие отладчиков связано со следующими принципиальными моментами:
- появлением интегрированных сред разработки;
- появление возможностей аппаратной поддержки
средств отладки во многих вычислительных системах.
Первый из этих шагов дал возможность разработчикам программ работать не в терминах машинных команд, а в терминах исходного языка программирования, что значительно сократило трудозатраты на отладку программного обеспечения.
Второй шаг позволяет значительно расширить возможности средств отладки. Теперь для них не требовалось моделировать работу и архитектуру соответствующей вычислительной системы. Выполнение результирующей программы в режиме отладки стало возможным в той же среде, что и в обычном режиме. B задачу отладчика входили только функции перевода вычислительной системы в соответствующий режим перед запуском результирующей программы на отладку. Bo многом эти функции являются приоритетными, поскольку зачастую требуют установки системных таблиц и флагов процессора вычислительной системы (мы рассмотрели большую часть этих вопросов в первой части данного учебного пособия).
Отладчики в современных системах программирования представляют собой модули с развитым интерфейсом пользователя, работающие непосредственно с текстом и модулями исходной программы. Многие их функции интегрированы с функциями текстовых редакторов исходных текстов, входящих в состав систем программирования.
Библиотеки подпрограмм составляют существенную часть систем программирования. Наряду с дружественностью пользовательского интерфейса состав доступных библиотек подпрограмм во многом определяет возможности системы программирования и ее позиции на рынке средств разработки программного обеспечения.
Библиотеки подпрограмм входили в состав средств разработки, начиная с самых ранних этапов их развития. Даже когда компиляторы еще представляли собой отдельные программные модули, они уже были связаны с соответствующими библиотеками, поскольку компиляция так или иначе предусматривает связь программ со стандартными функциями исходного языка. Эти функции обязательно должны входить в состав библиотек.
C точки зрения системы программирования, библиотеки подпрограмм состоят из двух основных компонентов. Это собственно файл (или множество файлов) библиотеки, содержащий объектный код, и набор файлов описаний функций, подпрограмм, констант и переменных, составляющих библиотеку. Описания оформляются на соответствующем входном языке (например, для языка C или C++ это будет набор заголовочных файлов). Иногда эти файлы могут быть совмещены.
Объектный код библиотеки подключается компоновщиком к результирующей программе при создании исполняемого модуля. По структуре он обычно мало чем отличается от обычных объектных файлов, порождаемых компилятором. Чаще всего система программирования хранит объектный код входящих в ее состав библиотек в некотором упакованном виде.
Набор файлов описания библиотеки служит для информирования компилятора о составе входящих в библиотеку функций. Обрабатывая эти файлы, компилятор получает всю необходимую информацию о составе библиотеки с точки зрения входного языка программирования. Эти файлы предназначены только для того, чтобы избавить разработчика от необходимости постоянного описания библиотечных функций, подпрограмм, констант и переменных.
B состав системы программирования может входить большое количество разнообразных библиотек. Среди них всегда можно выделить основную библиотеку, содержащую обязательные функции входного языка программирования. Эта библиотека всегда используется компилятором, поскольку без нее разработка программ на данном входном языке невозможна. Разработчик даже не должен указывать необходимость использования этой библиотеки (некоторые разработчики программ и не догадываются, что пользуются подобной библиотекой). Все остальные библиотеки необязательны и подключаются к результирующей программе только по прямому указанию разработчика.
B процессе развития систем программирования состав библиотек постоянно расширялся. B них включалось все большее и большее число функций. Это было вызвано тем, что система программирования, предоставляющая пользователю более широкий выбор библиотечных функций, получала лучшие позиции на рынке средств разработки программного обеспечения. Сами по себе библиотеки подпрограмм и функций, созданных для того или иного языка, также становились товаром на рынке средств разработки. Этот естественный процесс продолжается до сих пор, и чем длиннее история существования того или иного языка программирования, тем шире диапазон существующих для него библиотек.
Системы программирования для некоторых языков продолжают существовать во многом благодаря тому, что для них создан мощный аппарат библиотечных функций. Так язык FORTRAN существует благодаря широчайшему набору математических и физических функций, а язык COBOL - функций из финансо-. вой сферы.
B ходе развития систем программирования принципы создания и использования библиотечных функций претерпели мало изменений. Принципиально новые возможности предоставили только современные OC, которые позволили подключать к результирующим программам не статические, а динамические библиотеки.
Динамические библиотеки в отличие от традиционных (статических) библиотек подключаются к программе не в момент ее компоновки, а непосредственно в ходе выполнения, как только программа затребовала ту или иную функцию,
находящуюся в библиотеки. Преимущества таких библиотек очевидны - они не требуют включать в программу объектный код часто используемых функций, чем существенно сокращают объем кода. Различные программы, выполняемые в OC, могут пользоваться кодом одной и той же библиотеки, содержащейся в данной OC.
Формат файлов динамических библиотек может быть различным - как правило, он строго определяется требованиями соответствующей OC. Как и статические библиотеки, динамические библиотеки предусматривают описание входящих в них функций в виде текста на соответствующем входном языке, чтобы дать информацию о них компилятору в ходе обработки исходного текста программы и избавить разработчика от создания таких описаний.
Широкий набор динамических библиотек поддерживается всеми современными OC. Как правило, они содержат системные функции OC и общедоступные функции программного интерфейса (API). Кроме того, многие независимые разработчики предоставляют для различных систем программирования свои динамические библиотеки как отдельные товары на рынке средств разработки прикладных программ.
B современных OC появились средства, позволяющие поддерживать не только файлы, но и версии динамических библиотек. Они во многом используют методы, применяемые в системах управления версиями исходных файлов. Тогда приложение, обращаясь к библиотеке, может указать не только имя, но и требуемую версию вызываемой функции библиотеки.
В настоящее время в области системного программного обеспечения появляются новые версии операционных систем. К ним относятся:
- Linux, операционная система, работающая на разных аппаратных платформах и находящаяся в открытом доступе;
- Windows, широко распространенные операционные системы корпорации Microsoft, работающие на платформах x86, x86-64, IA-64, ARM.
Широкое применение находят операционные системы специального назначения на базе платформы Android.
Одно из главных преимуществ платформы Android – ее открытость, что позволяет разработчикам получить доступ к исходному коду Android и понять, каким образом реализованы свойства и функции приложений.
Проведем краткий обзор представленных операционных систем.
Ядро Linux - это центральная часть большой и сложной операционной системы. При этом, несмотря на размеры, оно имеет четкую структурную организацию в виде подсистем и уровней.
Операционную систему можно условно разделить на два уровня, как показано на рисунке 1.
Рис. 1. Структура Linux
Основная часть Linux независима от архитектуры, на которой работает операционная система, но в некоторых элементах для обеспечения нормальной работы и повышения эффективности необходимо учитывать архитектуру. В подкаталоге ./linux/arch находится архитектурно-зависимая часть исходного кода ядра, разделенная на ряд подкаталогов, соответствующих конкретным архитектурам.
Система Android – это программный стек для мобильных устройств, который включает операционную систему, программное обеспечение промежуточного слоя (middleware), а также основные пользовательские приложения (е-mаil-клиент, календарь, карты, браузер, контакты и др.).
Архитектуру Aпdroid принято делить на четыре уровня:
- уровень ядра;
- уровень библиотеки среды выполнения;
- уровень каркаса приложений;
- уровень приложений.
На рисунке 2 показаны основные компоненты операционной системы Android и их взаимодействие между собой.
Рис. 2. Структура Android
Ядро Android основано на ядре Linux версии 2.6 (для последних версий 4.X – 3.0), но сама система Android не является Linuх-системой в чистом виде, имеет некоторые отличия и содержит дополнительные расширения ядра, специфичные
Преимущество использования ядра Linux как основы Android в том, что ядро системы позволяет верхним уровням программного стека оставаться неизменными, несмотря на различия в используемом оборудовании. для Android, - свои механизмы распределения памяти, взаимодействие между процессам и и др.
Приложения и службы могут работать в защищенных отдельных процессах, которые должны общаться между собой и иметь доступ к общим данным.
Платформа Android предоставляет механизм IPC (Inter-process Communication), который является основным механизмом взаимодействия между процессами.
В данном учебном пособии рассмотрены вопросы назначения и функций операционных систем, назначение системы управления файлами, понятие операционной среды, понятие вычислительного процесса и ресурса, понятие вычислительного потока, понятие прерывания, управление задачами и памятью в операционных системах, файловые системы и управление вводом/выводом, понятие файловой системы, архитектура операционных систем, микроядерные и монолитные операционные системы а также архитектуры современного программного обеспечения
Данное учебное пособие предназначено для изучения теоретического материала по дисциплине «Операционные системы» для студентов направления 230100.62 заочной формы обучения.