Язык пакетных файлов должен обеспечивать последовательный запуск процессов, условные и безусловные переходы, организацию циклов и вложенных параметрических конструкций. В простейшем случае командный файл представляет собой последовательность интерактивных команд, записанную в специальный файл, предназначенный для автоматического исполнения. Для организации условных переходов в командных файлах необходима информация об успешности завершения процесса. Для этих целей вводится понятие кода завершения процесса, указываемого в системном вызове завершения (уничтожения) процесса. Зарезервированная переменная позволяет анализировать код завершения в командном файле. В командные файлы также включают средства генерации имен и вызова вспомогательных командных файлов с указанием параметров. Команды пакетных файлов приведены в таблице 3.3.
Таблица 3.3 – Команды пакетных файлов
Мнемоника
Наименование
Параметр 1
Параметр 2
Описание
Тип
Диапазон значений
Умолчания
if_proc_done <имя>
переход если процесс завершен
строка
-
-
-
если указанный процесс завершен то выполняется следующий блок команд
execute <N> <имя>
запуск процесса
число
[0;31]
строка
запуск процесса с указанным приоритетом
while_work <имя>
цикл, пока активен процесс
строка
-
-
-
пока процесс активен, выполняется следующий блок команд
goto <N>
переход на строку
число
переход на указанную строку пакетного файла
pause <сообщение>
пауза выполнения и вывод сообщения
строка
-
«Нажмите любую клавишу…»
-
приостанавливает выполнение команд, выводит сообщение на экран и ожидает нажатия любой клавиши
4 ОПРЕДЕЛЕНИЕ СОСТАВА И ОБЩЕЙ СТРУКТУРЫ СИСТЕМЫ
Фундаментальными понятиями теории операционных систем являются понятия файла и процесса. Файл представляет собой минимальную единицу хранения информации. Как правило, различают множество типов файлов, которые можно разделить на две группы: исполнимые файлы и файлы данных. Процесс создается в результате запуска исполнимого файла и представляет собой некоторую последовательность действий, выполняемую с использованием ресурсов компьютера. Понятия исполнимого файла и процесса не идентичны, поскольку один файл может быть запущен многократно, порождая несколько процессов.
Каждая операционная система создает собственную файловую и процессную среду. Один из главных вопросов при проектировании операционной системы является вопрос о том, что представляет собой операционная система с точки зрения собственной среды. С одной стороны система располагается в определенном наборе файлов, из которых она запускается при загрузке. С другой стороны для реализации функций ОС создается ряд специальных процессов, называемых системными.
4.1 Общее описание ядра и ОС
Операционная система компьютерной сети во многом аналогична ОС автономного компьютера — она также представляет собой комплекс взаимосвязанных программ, который обеспечивает удобство работы пользователям и программистам путем предоставления им некоторой виртуальной вычислительной системы, и реализует эффективный способ разделения ресурсов между множеством выполняемых в сети процессов.
Компьютерная сеть — это набор компьютеров, связанных коммуникационной системой и снабженных соответствующим программным обеспечением, позволяющим пользователям сети получать доступ к ресурсам этого набора компьютеров. Сеть могут образовывать компьютеры разных типов, которыми могут быть небольшие микропроцессоры, рабочие станции, мини-компьютеры, персональные компьютеры или суперкомпьютеры. Коммуникационная система может включать кабели, повторители, коммутаторы, маршрутизаторы и другие устройства, обеспечивающие передачу сообщений между любой парой компьютеров сети. Компьютерная сеть позволяет пользователю работать со своим компьютером как с автономным и добавляет к этому возможность доступа к информационным и аппаратным ресурсам других компьютеров сети.
При организации сетевой работы операционная система играет роль интерфейса, экранирующего от пользователя все детали низкоуровневых программно-аппаратных средств сети. Например, вместо числовых адресов компьютеров сети, таких как МАС-адрес и IP-адрес, операционная система компьютерной сети позволяет оперировать удобными для запоминания символьными именами. В результате в представлении пользователя сеть с ее множеством сложных и запутанных реальных деталей превращается в достаточно понятный набор разделяемых ресурсов.
Функциональная сложность операционной системы неизбежно приводит к сложности ее архитектуры, под которой понимают структурную организацию ОС на основе различных программных модулей. Обычно в состав ОС входят исполняемые и объектные модули стандартных для данной ОС форматов, библиотеки разных типов, модули исходного текста программ, программные модули специального формата (например, загрузчик ОС, драйверы ввода-вывода), конфигурационные файлы, файлы документации, модули справочной системы и т. д.
Для общего структурирования ОС классическими являются понятия ядра и системных процессов. Ядро - это та часть операционной системы, которая с точки зрения самой системы не является процессом. Ядро является продолжением аппаратных средств и упрощенно представляет собой набор обработчиков основных прерываний. Системные вызовы, как правило, реализуются посредством программных прерываний и представляют собой косвенный вызов модулей ядра со сменой режима работы процессора. Ядро реализует основные системные вызовы по управлению процессами и оперативной памятью, а также, в большинстве систем, функции обмена с внешними устройствами на физическом уровне (драйверы устройств). Другие системные вызовы переадресуются ядром для исполнения системным процессам. В форме специального системного процесса (файлового процессора) часто реализуются функции файловой системы. Для выполнения интерактивных команд и пакетных файлов также создаются системные процессы. При этом возможна реализация выполнения интерактивных команд всех терминалов одним системным процессом (командным процессором) либо запуск отдельного процесса для каждого подключенного терминала. Основные интерактивные команды выполняются командным процессором непосредственно, а для реализации дополнительных команд имеются специальные исполнимые файлы. Драйверы внешних устройств в некоторых ОС также представляются как системные процессы.
Первичное структурирование системы предполагает выделение ядра и системных процессов различных уровней и распределение их по файлам. Далее выполняется структурирование ядра и системных процессов путем выделения элементов данных и программ (модулей), имеющих определенное функциональное назначение.
Все операции, связанные с процессами, выполняются под управлением ядра ОС. Ядро представляет собой лишь небольшую часть кода ОС, однако оно относится к числу наиболее используемых компонент ОС. По этой причине ядро обычно резидентно и размещается в ОП, в то время, как другие части ОС перемещаются во внешнюю память и обратно по мере необходимости.
Ядро ОС обычно содержит программы для реализации следующих функций:
1) обработка прерываний:
а) создание и уничтожение процессов;
б) переключение состояний процессов;
в) диспетчеризация;
г) приостановка и активация;
д) синхронизация процессов;
е) организация взаимодействия между процессами;
2) поддержка операций ввода/вывода;
3) поддержка распределения, иерархирование памяти;
4) поддержка работы ФС;
5) поддержка механизма вызова возврата при обращении к процедурам (то есть возвращение в то место, откуда был произведен вызов);
6) поддержка определения функций по ведению учета машины.
Вход в ядро ОС обычно осуществляется по прерываниям. Когда ядро реагирует на данное прерывание, оно запрещает другие прерывания. После определения причины данного прерывания ядро передает его обработку специальному системному процессу, предназначаемому для работы с прерываниями данного типа. Схема прерываний для разных конфигураций ЭВМ отличается.
Схемы прерываний (типы):
1) прерывание по вызову супервизора(инициатором является работающий процессор);
2) прерывание ввода/вывода(инициируется аппаратурой ввода/вывода (когда завершается операция ввода/вывода, или совершается ошибка, или устройство переходит в другое состояние));
3) внешние прерывания(причиной могут быть различные события: истечение кванта времени, заданного на таймере, нажатие клавиши прерывания(ctrl+break); прием прерывания от другого процессора в мультипроцессорной системе);
4) прерывание по рестарту(происходит, когда оператор нажимает на пульте управления кнопку рестарта или от другого процессора в мультипроцессорной системе приходит такая команда);
5) прерывание по ошибке программыпри делении на 0, попытка процесса пользователя выполнить привилегированную операцию;
6) прерывание по ошибке машины(аппаратная ошибка: по питанию, испорченные области на диске).
Для обработки каждого из этих типов прерываний предусмотрены программы, называемые обработчиками прерываний. Когда происходит прерывание, ОС запоминает состояние прерванного процесса и передает управление соответствующему обработчику прерываний. Когда обработка прерывания завершается, ЦП начинает обслуживать либо тот процесс, который выполнялся во время прерывания, либо готовый процесс с наивысшим приоритетом.
4.2 Ядро и вспомогательные модули ОС
Наиболее общим подходом к структуризации операционной системы является разделение всех ее модулей на две группы:
- ядро — модули, выполняющие основные функции ОС;
- модули, выполняющие вспомогательные функции ОС.
Модули ядра выполняют такие базовые функции ОС, как управление процессами, памятью, устройствами ввода-вывода и т. п. Ядро составляет сердцевину операционной системы, без него ОС является полностью неработоспособной и не сможет выполнить ни одну из своих функций.
В состав ядра входят функции, решающие внутрисистемные задачи организации вычислительного процесса, такие как переключение контекстов, загрузка/выгрузка станиц, обработка прерываний. Эти функции недоступны для приложений. Другой класс функций ядра служит для поддержки приложений, создавая для них так называемую прикладную программную среду. Приложения могут обращаться к ядру с запросами — системными вызовами — для выполнения тех или иных действий, например для открытия и чтения файла, вывода графической информации на дисплей, получения системного времени и т. д. Функции ядра, которые могут вызываться приложениями, образуют интерфейс прикладного программирования — API.
Функции, выполняемые модулями ядра, являются наиболее часто используемыми функциями операционной системы, поэтому скорость их выполнения определяет производительность всей системы в целом. Для обеспечения высокой скорости работы ОС все модули ядра или большая их часть постоянно находятся в оперативной памяти, то есть являются резидентными.
Остальные модули ОС выполняют весьма полезные, но менее обязательные функции. Например, к таким вспомогательным модулям могут быть отнесены программы архивирования данных на магнитной ленте, дефрагментации диска, текстового редактора. Вспомогательные модули ОС оформляются либо в виде приложений, либо в виде библиотек процедур.
Вспомогательные модули ОС подразделяются на следующие группы:
- утилиты — программы, решающие отдельные задачи управления и сопровождения компьютерной системы, такие, например, как программы сжатия дисков, архивирования данных на магнитную ленту;
- системные обрабатывающие программы — текстовые или графические редакторы, компиляторы, компоновщики, отладчики;
- программы предоставления пользователю дополнительных услуг — специальный вариант пользовательского интерфейса, калькулятор и даже игры;
- библиотеки процедур различного назначения, упрощающие разработку приложений, например библиотека математических функций, функций ввода-вывода и т. д.
Как и обычные приложения, для выполнения своих задач утилиты, обрабатывающие программы и библиотеки ОС, обращаются к функциям ядра посредством системных вызовов (рис. 1).
Разделение операционной системы на ядро и модули-приложения обеспечивает легкую расширяемость ОС. Чтобы добавить новую высокоуровневую функцию, достаточно разработать новое приложение, и при этом не требуется модифицировать ответственные функции, образующие ядро системы. Однако внесение изменений в функции ядра может оказаться гораздо сложнее, и сложность эта зависит от структурной организации самого ядра. В некоторых случаях каждое исправление ядра может потребовать его полной перекомпиляции.
Рисунок 4.1 – Взаимодействие между ядром и вспомогательными модулями ОС
Модули ОС, оформленные в виде утилит, системных обрабатывающих программ и библиотек, обычно загружаются в оперативную память только на время выполнения своих функций, то есть являются транзитными. Постоянно в оперативной памяти располагаются только самые необходимые коды ОС, составляющие ее ядро. Такая организация ОС экономит оперативную память компьютера.
Важным свойством архитектуры ОС, основанной на ядре, является возможность защиты кодов и данных операционной системы за счет выполнения функций ядра в привилегированном режиме.
Для надежного управления ходом выполнения приложений операционная система должна иметь по отношению к приложениям определенные привилегии. Иначе некорректно работающее приложение может вмешаться в работу ОС и, например, разрушить часть ее кодов. Все усилия разработчиков операционной системы окажутся напрасными, если их решения воплощены в незащищенные от приложений модули системы, какими бы элегантными и эффективными эти решения ни были. Операционная система должна обладать исключительными полномочиями также для того, чтобы играть роль арбитра в споре приложений за ресурсы компьютера в мультипрограммном режиме. Ни одно приложение не должно иметь возможности без ведома ОС получать дополнительную область памяти, занимать процессор дольше разрешенного операционной системой периода времени, непосредственно управлять совместно используемыми внешними устройствами.
Обеспечить привилегии операционной системе невозможно без специальных средств аппаратной поддержки. Аппаратура компьютера должна поддерживать как минимум два режима работы — пользовательский режим (user mode) и привилегированный режим, который также называют режимом ядра (kernel mode), или режимом супервизора (supervisor mode). Подразумевается, что операционная система или некоторые ее части работают в привилегированном режиме, а приложения — в пользовательском режиме.
Так как ядро выполняет все основные функции ОС, то именно ядро становится той частью ОС, которая работает в привилегированном режиме Иногда это свойство — работа в привилегированном режиме — служит основным определением понятия «ядро».
Структуру ОС составляют следующие модули:
– базовый модуль (ядро ОС) – управляет работой программы и файловой системой, обеспечивает доступ к ней и обмен файлами между периферийными устройствами;
– командный процессор – расшифровывает и исполняет команды пользователя, поступающие прежде всего через клавиатуру;
– драйверы периферийных устройств – программно обеспечивают согласованность работы этих устройств с процессором (каждое периферийное устройство обрабатывает информацию по-разному и в различном темпе);
– дополнительные сервисные программы (утилиты) – делают удобным и многосторонним процесс общения пользователя с компьютером.
4.3 Загрузка и модули ядра ОС
Для выполнения программы и файлы ОС должны находится в оперативной памяти (ОЗУ). Чтобы произвести запись ОС в ОЗУ, необходимо выполнить программу загрузку, которой сразу после включения компьютера в ОЗУ нет. Выход из этой ситуации состоит в последовательной, поэтапной загрузке ОС в оперативную память. Рассмотрим этапы загрузки операционной системы:
а) первый этап загрузки ОС: в системном блоке компьютера находится постоянное запоминающее устройство (ПЗУ, постоянная память, ROM-Read Only Memory - память с доступом только для чтения), в котором содержатся программы тестирования блоков компьютера и первого этапа загрузки ОС. Они начинают выполнятся с первым импульсом тока при включении компьютера. На этом этапе процессор обращаются к диску и проверяет наличие на определенном месте (в начале диска) очень небольшой программы - загрузчика. Если эта программа обнаружена, то она считывается в ОЗУ и ей передается управление.
б) второй этап загрузки ОС: программа-загрузчик ищет на диске базовый модуль ОС, переписывает его память и передает ему управление.
в) третий этап загрузки ОС: в состав базового модуля входит основной загрузчик, который ищет остальные модули ОС и считывает их в ОЗУ. После окончания загрузки ОС управление передается командному процессору и на экране появляется приглашение системы к вводу команды пользователя.
В оперативной памяти во время работы компьютера обязательно должны находится базовый модуль ОС и командный процессор. Следовательно, нет необходимости загружать в оперативную память все файлы ОС одновременно. Драйверы устройств и утилиты могут подгружаться в ОЗУ по мере необходимости, что позволяет уменьшать обязательный объем оперативной памяти, отводимый под системное программное обеспечение.
В состав операционной системы входят следующие файлы:
loadeк.com – загрузчик операционной системы. Выполняет загрузку ядра, всех драйверов и параметров, а также загрузку модулей ОС. Файл загружается при запуске операционной системы.
kernel.sys – ядро операционной системы. После загрузки запускает к выполнению основные системные процессы. К которым относятся планировщик процессов, а также модуль управления памятью и межпроцессным взаимодействием.
Модули ядра операционной системы представлены в таблице 4.1.
Таблица 4.1– Модули ядра
Наименование
Назначение
Обрабатываемые прерывания
procman
является планировщиком процессов, обеспечивает все выполняемые процессы необходимыми ресурсами
обрабатывает все виды прерываний
memman
управляет оперативной и виртуальной памятью
обрабатывает программные прерывания
interproc
передача данных между различными процессами
обрабатывает программные и аппаратные прерывания
command_proc.com
обработка команд пользователя
обрабатывает аппаратные прерывания
filesys.com
работа с файловой системой
обрабатывает программные и аппаратные прерывания
Планировщик процессов разрешает конфликты между процессами в конкуренции за системные ресурсы (процессор, память, устройства ввода/вывода); следит, чтобы процесс монопольно не захватил разделяемые системные ресурсы. Процесс освобождает процессор, ожидая длительной операции ввода/вывода, или по прошествии кванта времени.
Модуль управления памятью обеспечивает выделение оперативной памяти для прикладных программ; реализует доступ к виртуальной памяти; управляет виртуальной памятью процессов.
Модуль межпроцессного взаимодействия отвечает за уведомление процессов о событиях с помощью системы команд и обеспечивает возможность передачи данных между различными процессами.
command_proc.com – командный процессор. Необходим для обработки команд пользователя. Запускается после ядра системы.
filesys.com – файловый процессор. Главной задачей файлового процессора является работа с файловой системой (выполнения различных команд пользователя, например, таких как удаление, копирование, переименование файлов).
Ядро ОС имеет интерфейс системных вызовов. Именно через него процесс производит запрос необходимых ресурсов, а ядро операционной системы либо отвергает запрос, либо обеспечивает процесс запрашиваемыми ресурсами.
При запуске операционной системы в первую очередь запускается файл «loader.com». Который запускает ядро ОС, подгружает все необходимые драйвера и пользовательские настройки системы. Все вышеописанные модули на протяжении всего времени работы операционной системы находятся в памяти и обеспечивают корректную работу ОС.
4.4 Структура ядра ОС
Как и в любой другой многопользовательской операционной системе, обеспечивающей защиту пользователей друг от друга и защиту системных данных от любого непривилегированного пользователя, в ОС имеется защищенное ядро, которое управляет ресурсами компьютера и предоставляет пользователям базовый набор услуг.
Следует заметить, что удобство и эффективность современных вариантов ОС не означает, что вся система, включая ядро, спроектирована и структуризована наилучшим образом.
В результате, ядро большинства современных коммерческих вариантов ОС) представляет собой не очень четко структуризованный монолит большого размера. Операционная система обладает классическим монолитным ядром, в котором можно выделить следующие основные части:
- Файловая подсистема. Доступ к структурам ядра осуществляется через файловый интерфейс.
- Управление процессами. Сюда входит управление параллельным выполнением процессов (планирование и диспетчеризация), виртуальной памятью процесса и взаимодействием между процессами (сигналы, очереди сообщений и т. п.).
- Драйверы устройств. Драйверы устройств делятся на символьные и блочные по типу внешнего устройства. Для каждого из устройств определен набор возможных операций (открытие, чтение и т. д.). Блочные устройства кэшируются с помощью специального внутреннего механизма управления буферами.
Благодаря тому, что в UNIX аппаратно-независимая часть отделена явно, операционные системы этого семейства могут быть с минимальными затратами перенесены на новые аппаратные платформы.
Рисунок 4.2 — Ядро ОС
4.5 Системные вызовы
Системные вызовы (system calls) интерфейс между операционной системой и пользовательской программой. Они создают, удаляют и используют различные объекты, главные из которых процессы и файлы. Пользовательская программа запрашивает сервис у операционной системы, осуществляя системный вызов. Имеются библиотеки процедур, которые загружают машинные регистры определенными параметрами и осуществляют прерывание процессора, после чего управление передается обработчику данного вызова, входящему в ядро операционной системы. Цель таких библиотек сделать системный вызов похожим на обычный вызов подпрограммы.
Основное отличие состоит в том, что при системном вызове задача переходит в привилегированный режим или режим ядра (kernel mode). Поэтому системные вызовы иногда еще называют программными прерываниями в отличие от аппаратных прерываний, которые чаще называют просто прерываниями.
В этом режиме работает код ядра операционной системы, причем он исполняется в адресном пространстве и в контексте вызвавшей его задачи. Таким образом, ядро операционной системы имеет полный доступ к памяти пользовательской программы, и при системном вызове достаточно передать адреса одной или нескольких областей памяти с параметрами вызова и адреса одной или нескольких областей памяти для результатов вызова.
Системный вызов позволяет приложению обратиться к операционной системе для выполнения действий, входящих в прерогативу ядра ОС, т.е. запрещенных в пользовательском режиме. Реализация системных вызовов должна обладать следующими свойствами:
- Обеспечивать переключение в привилегированный режим (выполняет механизм прерываний)
- выполняться быстро;
- иметь одинаковый вид в разных аппаратных платформах;
- допускать легкое расширение набора системных вызовов;
- Выполняться под контролем ОС.
Диспетчер системных вызовов контролирует запрос и передает вызов процедуре ОС, адрес которой определяется номером запроса. Процедура, если надо, выбирает из стека данные для своей работы, возможно, обращается к некоторым подсистемам ядра ОС, а после завершения работы возвращает управление диспетчеру системных вызовов.
Для приложения, системный вызов внешне ничем не отличается от вызова функции из библиотеки функций языка С.
Операционная система может выполнять системные вызовы в синхронном и асинхронном режимах. При синхронном, процесс, сделавший системный вызов, блокируется до окончания обработки, при асинхронном – может быть продолжен до момента, когда необходим результат. При этом он может быть прерван другим потоком. Большинство системных вызовов является синхронными, при работе микроядерной ОС – асинхронными.
При обращении к системным вызовам, поддерживаемым ОС, параметры помещаются в строго определенные места, такие, как регистры или стек, а затем выполняется специальная команда прерывания, известная как вызов ядра или вызов супервизора. Эта команда переключает машину из режима пользователя в режим ядра, называемый также режимом супервизора, и передает управление ОС. Затем ОС проверяет параметры вызова для того, чтобы определить, какой системный вызов должен быть выполнен. После этого ОС индексирует таблицу, содержащую ссылки на процедуры, и вызывает соответствующую процедуру. Такая организация ОС предполагает следующую структуру:
1. Главная программа, которая вызывает требуемые сервисные процедуры.
2. Набор сервисных процедур, реализующих системные вызовы.
3. Набор утилит, обслуживающих сервисные процедуры.
В этой модели для каждого системного вызова имеется одна сервисная процедура. Утилиты выполняют функции, которые нужны нескольким сервисным процедурам.
Для обеспечения передачи параметров диспетчеру системных вызовов и процедурам ОС могут использоваться различные механизмы:
– передача параметров через регистры (самый быстрый механизм, но сильное ограничение по количеству передаваемой информации);
– передача параметров через область памяти, адрес которой заносится в регистр (позволяет передать максимально возможное количество параметров);
– передача параметров через стек процесса (не задействуем дополнительный регистр, нет проблем с памятью, так как параметры будут сразу помещены в доступную для процесса память).
Реализация системных вызовов должна:
– обеспечивать переключение в режим ядра;
– обладать высокой скоростью вызовов процедур ОС;
– обеспечивать единообразное обращение к системным вызовам для всех
аппаратных платформ, на которых работает ОС;
– обладать свойством расширяемости;
– обеспечивать контроль со стороны ОС за корректностью использованных системных вызовов.
4.5.1 Процессы
Процесс в ОС - это программа, выполняемая в собственном виртуальном адресном пространстве. Когда пользователь входит в систему, автоматически создается процесс, в котором выполняется программа командного интерпретатора. Если командному интерпретатору встречается команда, соответствующая выполняемому файлу, то он создает новый процесс и запускает в нем соответствующую программу, начиная с функции main. Эта запущенная программа, в свою очередь, может создать процесс и запустить в нем другую программу (она тоже должна содержать функцию main) и т.д.
Для образования нового процесса и запуска в нем программы используются два системных вызова (примитива ядра ОС) - fork() и exec (имя-выполняемого-файла). Системный вызов fork приводит к созданию нового адресного пространства, состояние которого абсолютно идентично состоянию адресного пространства основного процесса (т.е. в нем содержатся те же программы и данные).
Сразу после выполнения системного вызова fork основной и порожденный процессы являются абсолютными близнецами; управление и в том, и в другом находится в точке, непосредственно следующей за вызовом fork. Чтобы программа могла разобраться, в каком процессе она теперь работает - в основном или порожденном, функция fork возвращает разные значения: 0 в порожденном процессе и целое положительное число (идентификатор порожденного процесса) в основном процессе.
Теперь, если нужно запустить новую программу в порожденном процессе, нужно обратиться к системному вызову exec, указав в качестве аргументов вызова имя файла, содержащего новую выполняемую программу, и, возможно, одну или несколько текстовых строк, которые будут переданы в качестве аргументов функции main новой программы. Выполнение системного вызова exec приводит к тому, что в адресное пространство порожденного процесса загружается новая выполняемая программа и запускается с адреса, соответствующего входу в функцию main.