- •Архитектура семейства ос Unix
- •6.1. История и современное состояние
- •6.2. Архитектура Unix
- •6.3. Процессы
- •6.4. Нити
- •6.5. Планирование процессов
- •6.6. Управление памятью
- •6.7. Средства взаимодействия процессов
- •6.8. Файловые системы
- •Файловая система s5
- •Файловая система ufs
- •Файловая система sfs
- •Файловая система Veritas
- •Другие файловые системы Open Unix
- •Файловая система jfs
- •6.9. Интерфейсы Unix
- •6.10. Unix-системы фирмы Caldera
6.2. Архитектура Unix
Архитектура ОС Unix [14] представлена на рисунке 6.1.
Рисунок 6.1 Архитектура Unix |
Хотя эта архитектура объявлена как иерархическая, в ней просматриваются всего три уровня иерархии: ядро, системные утилиты, процессы пользователей. Само ядро Unix, таким образом, является монолитным, хотя некоторая (не формулируемая декларативно) структурированность в нем, конечно же, имеется. Так, в Unix различаются две принципиально различные группы системных вызовов: внутренние, которые доступны для пользовательских процессов и составляют собственно API ОС, и внешние, употребляемые только из модулей ядра. Весьма тщательно выполнено разделение ядра на аппаратно-зависимую и аппаратно-независимую части.
Модули первой части пишутся на языке Ассемблера целевой платформы и выполняют:
загрузку и инициализацию ОС;
переключение контекста;
управление реальной памятью;
первичную (низкоуровневую) обработку прерываний;
низкоуровневое управление устройствами (аппаратные драйверы).
Модули второй части написаны на языке C и обеспечивают высокоуровневую обработку, в том числе:
порождение, планирование и прочее управление процессами и (в поздних реализациях) нитями:
управление виртуальной памятью;
средства взаимодействия между процессами;
поддержку файловой системы;
логическую обработку прерываний;
высокоуровневые функции драйверов устройств;
поддержку API.
Обращения процессов к системе имеют вид программных прерываний, но из прикладной программы обращение к ОС имеет вид вызова библиотечных функций, написанных на языке C. Модули библиотеки системных вызовов аппаратно-зависимые и содержат обращения к ядру с использованием тех механизмов программного прерывания, которые доступны на данной аппаратной платформе.
6.3. Процессы
Концепция процесса в том виде, в каком она представлена в нашей книге, родилась именно в MULTICS и Unix. Процессом является выполняемая программа, которая представляет собой последовательности байтов, интерпретируемые процессором как машинные команды, данные и стековые структуры.
Контекстом процесса в Unix является его состояние, определяемое содержимым адресного пространства процесса, значениями глобальных переменных пользователя и информационными структурами, содержимым машинных регистров, значениями, хранимыми в строке таблицы процессов, а также содержимым стеков задачи и ядра данного процесса. Коды модулей ОС и общие информационные структуры, совместно использующиеся всеми процессами, не являются составной частью контекста процесса.
Вся работа системы происходит в контексте какого-либо процесса. Если процесс выполняет системный вызов, при котором происходит переход в режим ядра, то меняется режим, но не контекст. Модули ядра, следовательно, выполняются в контексте процесса и используют ресурсы того процесса, для которого они выполняются. Прерывания также выполняются в контексте процесса - того процесса, который был прерван, даже если прерывание не имеет отношения к этому процессу. Программы обработки прерываний обычно не работают со статической составляющей контекста процесса, так как эта часть не связана с прерываниями.
В системе процесс представляется строкой в таблице процессов. В ранних версиях Unix таблица процессов и другие системные структуры данных в памяти, располагались в статической памяти, имели фиксированный размер и смежное размещение. Позднее эти структуры стали располагаться в динамически выделяемой памяти со связным размещением, что дает возможность изменять их размер. Строка таблицы процессов содержит такую информацию о процессе, которая используется вне его контекста, например: идентификатор процесса, состояние процесса, его приоритет и т.д., а также указатели на структуры, описывающие контекст процесса.
Контекст процесса состоит из пользовательской и системной составляющих.
Пользовательский контекст включает в себя содержимое адресного пространства процесса (программного кода, данных, стека) и вектор состояния (содержимое аппаратных регистров).
Системный контекст содержит структуры данных ядра, связанные с этим процессом. Системный контекст процесса в Unix состоит из статической и динамических частей. Для каждого процесса имеется одна статическая часть контекста системного уровня и переменное число динамических частей.
Статическая часть системного контекста процесса включает в себя:
строку таблицы процессов;
часть адресного пространства задачи, выделенную процессу, где хранится управляющая информация о процессе; эта информация недоступна самому процессу, но может использоваться ядром только в контексте процесса;
структуры данных, описывающие виртуальное адресное пространство процесса; если два или более процессов используют разделяемые сегменты памяти (см. ниже), то соответствующие структуры данных включаются в системный контекст каждого из этих процессов.
Динамическая часть системного контекста процесса представляет собой стек ядра.
Стек, входящий в состав пользовательской части контекста процесса, предназначается для размещения в нем локальных переменных и обеспечения возвратов из вложенных вызовов процедур. Однако, как мы сказали выше, процесс может выполняться как в режиме процесса, так и в режиме ядра (точнее - модули ядра выполняются в контексте процесса). Динамическая часть системного процесса предназначена для обеспечения функционирования в режиме ядра. Выполнение модулей в режиме ядра может прерываться так же, как и выполнение модулей в режиме процесса. ОС Unix рассчитана на некоторую иерархию прерываний: каждое прерывание имеет некоторый уровень приоритета, и обработка прерывания какого-то уровня может быть прервано прерыванием с более высоким уровнем приоритета. Уровни приоритетов прерываний обычно поддерживаются аппаратной платформой. Типовое распределение уровней приоритетов (в порядке возрастания) следующее:
программные прерывания,
прерывания от терминалов,
прерывания от сетевого оборудования,
прерывания от дисков,
прерывания от таймера,
исключения (машинные сбои и исключительные ситуации).
Для каждого уровня прерывания создается свой стек ядра (или выделяется уровень в общем стеке ядра). В стеке i-го уровня сохраняется вектор состояния прерванного i-1-го уровня (в стеке нижнего уровня - сохраняется вектор состояния прерванного процесса) и выделяется рабочее пространство стека для поддержки выполнения i-го уровня (например, для размещения его локальных переменных). Число стеков ядра (число динамических составляющих системного контекста) определяется количеством уровней прерываний, зависящим от платформы.
