3.1 Особенности архитектуры ОС Unix

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

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

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

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

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

3.2. Структура ядра Unix

Ядро непосредственно взаимодействует с аппаратной частью компьютера, изолируя прикладные программы (процессы в пользовательской части операционной системы) от особенностей ее архитектуры. Ядро имеет набор услуг, предоставляемых прикладным программам посредством системных вызовов. Таким образом, в системе можно выделить два уровня привилегий: уровень системы (привилегии специального пользователя root) и уровень пользователя (привилегии всех остальных пользователей). Важной частью системных программ являются демоны. Демон – это процесс, выполняющий определенную функцию в системе, который запускается при старте системы и не связан ни с одним пользовательским терминалом. Демоны предоставляют пользователям определенные сервисы, примерами которых могут служить системный журнал, веб-сервер и т.п. (рис. 3.1).


Рисунок 3.1. - Архитектура операционной системы UNIX

Операционная система UNIX обладает классическим монолитным ядром, в котором можно выделить следующие основные части:

  • Файловая подсистема. Доступ к структурам ядра осуществляется через файловый интерфейс;
  • Управление процессами. Сюда входит управление параллельным выполнением процессов (планирование и диспетчеризация), виртуальной памятью процесса, и взаимодействием между процессами (сигналы, очереди сообщений и т.п.). [1]

Структуру ядра Unix можно представить, как показано на рис. 3.2.

Системный интерфейс

Компонент Ввода-вывода

Компонент управления памятью

Компонент управления процессами

Виртуальная файловая система

Виртуальная память

Обработка сигналов

Файловая система

Сокеты

Терминалы

Обобщенный уровень блочных устройств

Сетевые протоколы

Дисциплины линий связи

Механизм замещения страниц

Создание и завершение процессов и потоков

Диспетчер блочных устройств

Драйверы сетевых устройств

Драйверы символьных устройств

Кэш страниц

Планирование процессов

Диспетчер прерываний

Аппаратура

Рисунок 3.2 – Структура ядра Unix

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

Ядро Linux можно разделить на 3 части:

  1. Компонент ввода-вывода.
  2. Компонент управления памятью.
  3. Компонент управления процессами.

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

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

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

Компонент управления памятью. В задачи управления памятью входят:

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

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

Все рассмотренные компоненты взаимосвязаны друг с другом. Файловые системы обращаются к файлам через блочные устройства, однако, если в данный момент в памяти отсутствует свободное место, то в данном случае необходимо задействовать компонент управления памятью для выгрузки и загрузки соответствующих страниц. [2]

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

Системные вызовы обеспечивают:

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

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

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

Пространство (памяти) ядра - это область памяти, в которой процессы ядра (процессы, работающие в контексте ядра) реализуют службы ядра. Любой процесс, выполняющийся в пространстве ядра, считается работающим в режиме ядра. Пространство ядра - привилегированная область; пользователь получает к ней доступ только через интерфейс системных вызовов. Пользовательский процесс не имеет прямого доступа ко всем инструкциям и физическим устройствам, - их имеет процесс ядра. Процесс ядра также может менять карту памяти, что необходимо для переключения процессов (смены контекста). Пользовательский процесс работает в режиме ядра, когда начинает выполнять код ядра через системный вызов. [3]

3.3. Загрузка ОС Unix. Этапы и уровни загрузки

Загрузку операционной системы семейства Unix можно разделить на несколько этапов. Начальный этап загрузки не зависит от того, какая операционная система установлена на компьютере, он в первую очередь связан с особенностями архитектуры используемого компьютера. Затем следуют этапы загрузчиков, которые также могут не относиться к определённым операционным системам, после чего инициализируется ядро операционной системы, и производятся специфические только для этой ОС операции.

Рассмотрим загрузку операционной системы UNIX как следующую последовательность этапов (рисунок 3.3):


Рисунок 3.3 - Этапы загрузки ОС UNIX

Досистемный загрузчик. Как правило, сразу после включения питания программа ПЗУ BIOS проводит тестирование оборудования, затем запускается досистемный загрузчик. Задача этого этапа – определить (возможно, с помощью пользователя), с какого устройства будет идти загрузка, загрузить оттуда специальную программу-загрузчик и запустить её. Например, выяснить, что устройство для загрузки – жесткий диск, считать самый первый сектор этого диска и передать управление программе, которая находится в считанной области.

Загрузчик первого уровня занимает обычно не более одного сектора в самом начале диска – в его загрузочном секторе (Master Boot Record). Ядро операционной системы имеет довольно сложную структуру – а значит, и непростой способ загрузки; оно может быть довольно большим, и может располагаться неизвестно где на диске, подчиняясь законам файловой системы (например, состоять из нескольких частей, разбросанных по диску). Учесть все это первичный загрузчик не в состоянии, поэтому его задача: определить, где на диске находится загрузчик второго уровня, загрузить его в память и передать ему управление.

Загрузчик второго уровня - сложная программа с интерфейсом пользователя, который даёт возможность выбирать операционную систему или параметры загрузки ядра. Загрузчик должен иметь доступ к образу ядра, поэтому в него включается поддержка файловых систем. Вторичный загрузчик читает образ ядра в определённый адрес памяти и передаёт туда управление. Большинство операционных систем имеют собственные загрузчики первого и второго уровней. Однако, существуют универсальные загрузчики, например GRUB. Загрузчик GRUB берет свои настройки из конфигурационного файла /boot/grub/grub.conf или /boot/grub/menu.lst. При подготовке GRUB загружает в память ядро из каталога /boot.

Инициализация ядра операционной системы. Прежде чем начать работу с системой, её необходимо проинициализировать. Этот этап специфичен для различных операционных систем. В UNIX-подобных системах при этом обычно выводится информация о загрузке ядра отладочного характера. Сначала ядро занимается определением параметров вычислительной подсистемы компьютера: выясняет тип и быстродействие центрального процессора, объем оперативной памяти, объем и структуру кэш-памяти; делает предположение об архитектуре компьютера в целом и др.

На следующем шаге ядро определяет состав и архитектуру всего аппаратного наполнения компьютера: тип и параметры шин передачи данных и устройств управления ими (контроллеров), список внешних устройств, доступных по шинам, настройки этих устройств – диапазон портов ввода-вывода, адрес ПЗУ, занимаемое аппаратное прерывание, номер канала прямого доступа к памяти и т.п.

Ядро на основании переданного ему параметра выбирает корневой раздел – файловую систему, содержащую будущий каталог /и его подкаталоги (для системной начальной загрузки важны каталоги/etc, /bin, и /sbin). Корневой раздел монтируется в качестве /. После этого ядро запускает свой первый процесс –init (по умолчанию /sbin/init).

Процесс init. В UNIX первым запускаемым процессом является init. С этого момента операционная система обеспечивает полноценную функциональность всем исполняющимся процессам.

Процесс init является обычным процессом операционной системы, однако он имеет некоторые особенности: его PID всегда равен 1, и процесс этот работает всё время, пока работает система.

В UNIX-системах init играет две важные роли:

  • производит инициализацию системы – как правило, для работы запущенного ядра не достаточно, нужно примонтировать все файловые системы, загрузить дополнительные драйверы устройств, запустить демоны и т.п.;
  • является родительским для всех процессов в системе – это является гарантией того, что в UNIX любой процесс имеет своего родителя. [4]

Источники:

1. Студопедия. Особенности архитектуры Unix и Linux. - URL: https://studopedia.ru/9_38230_zanyatie--osobennosti-arhitekturi-Unix-i-Linux.html

2. StudFiles. Структура ядра ОС Linux. – URL: https://studfiles.net/preview/5357373/page:2/

3. Студопедия. Структура ядра системы UNIX. – URL: https://studopedia.ru/6_12422_struktura-yadra-sistemi-UNIX.html

4. StudFiles. Базовое администрирование unix. - URL: https://studfiles.net/preview/2609483/