Этот этап реализуется не ОС, а системами программирования, основным функциональным назначением которых является генерация объектного кода программы (машинных команд). Основным компонентом системы программирования является компилятор. На вход компилятора поступает исходный модуль – текст программы на языке программирования. Выходом компилятора является объектный модуль – программа в машинных кодах, к которой, однако, еще не подключены внешние процедуры и функции. Компилятор предварительно формирует структуру виртуального адресного пространства: определяют состав сегментов и формируют содержимое (образы) кодовых сегментов и сегментов инициализированных статических данных. С целью получения наиболее эффективного объектного кода компиляторы могут выполнять оптимизацию обрабатываемой программы. Для программ, предназначенных к выполнению на RISC-процессорах, оптимизация является обязательной, так как позволяет эффективно загрузить конвейерные линии процессора.
Формирование единой программы из нескольких объектных модулей называется компоновкой. Обеспечение обращений к внешним по отношению к модулю именам называется связыванием. Операции компоновки и связывания выполняются специальными программами - компоновщиками (редакторами связей) или связывающими загрузчиками. Операцию связывания можно выполнять на разных этапах:
· статическое связывание этапа подготовки - выполняется компоновщиком, вызываемые модули включаются в загрузочный модуль программы;
· статическое связывание этапа загрузки - выполняется связывающим загрузчиком, вызываемые модули подключаются к программе уже в ОП;
· динамическое связывание этапа загрузки - отличается от предыдущего варианта тем, что обеспечивает совместное использование одних и тех же копий модулей в памяти разными программами; в некоторых реализациях модули загружаются в память совместно с основной программой, связи устанавливаются при загрузке или при обращении;
· динамическое связывание этапа выполнения - загрузка модулей и установка связей происходит при выполнении программы и управляет ими сама программа.
Современные ОС (Windows 9х, OS/2 и т.д.) позволяют сочетать статическую компоновку и связывание с динамической. Модули, подключаемые к программам динамически, носят название библиотек динамической компоновки (dynamic link library), соответственно, файлы, содержащие образы таких модулей имеют расширения DLL. DLL широко используются для системного программного обеспечения. API ОС, средства работы с терминалом, графические средства и т.п. представляют собой библиотеки динамической компоновки, совместно используемые всеми программами. При загрузке любой программы эти модули, как правило, уже находятся в памяти.
Цикл жизни процесса
Программа, готовая к выполнению, превратится в процесс только тогда, когда ОС создаст для нее блок контекста и запись в системной таблице процессов. ОС существенно различаются по тому признаку, насколько часто они создают новые процессы и сколько процессов могут одновременно существовать в системе. В однозадачных системах существует один процесс (или несколько процессов, только один из которых - пользовательский), который последовательно выполняет одну программу за другой. Различные подходы могут применяться в многозадачных интерактивных системах. Во-первых, с каждым терминалом может связываться единственный процесс-сеанс, пользователь каждого терминала работает как бы в однозадачной среде. Во-вторых, для преодоления стесненности пользователя в сеансе система может позволять ему в ходе сеанса порождать дополнительные процессы. В-третьих, система может позволять порождать любые процессы и в любом количестве.
Процессы в системе могут либо существовать как отдельные не связанные друг с другом единицы, либо образовывать какие-либо структуры. Обычно модель независимого существования процессов используется в тех ОС, которые накладывают ограничения на возможности создания процессов.
В тех ОС, которые разрешают процессам в свою очередь порождать новые процессы, применяется иерархическая структура связей между процессами, в которой между процессами существуют отношения "родитель-потомок". Передача ресурсов от предка к потомку позволяет родственным процессам легко устанавливать связи друг с другом. Процесс-потомок может быть запущен синхронно или асинхронно с родителем. При синхронном запуске процесс-родитель блокируется до завершения процесса-потомка. При асинхронном запуске родитель и потомок продолжают выполняться параллельно и могут взаимодействовать. Если родителю необходимо дождаться завершения потомка, он выдает системный вызов ожидания. Синхронный запуск не является обязательной возможностью, так как тот же эффект может быть обеспечен парой вызовов: "асинхронный запуск" - "ожидание".
Для того, чтобы родитель мог воздействовать на потомка, вызов запуска возвращает ему идентификатор (манипулятор) порожденного процесса. Этот идентификатор используется родителем при последующих воздействиях на потомка. Потомок может в свою очередь создавать новые процессы, то есть, стать во главе целого подсемейства (поддерева) процессов.