Индекс
НазадОглавлениеВперед

Глава 6. Семейство ОС Unix

6.1. История и современное состояние

Писать об ОС Unix чрезвычайно трудно. Во-первых, потому, что об этой системе написано очень много. Во-вторых, потому, что идеи и решения Unix оказали и оказывают огромное влияние на развитие всех современных ОС, и многие из этих идей уже описаны в этой книге. В-третьих, потому что Unix - не одна ОС, а целое семейство систем, и не всегда можно "отследить" их родство между собой, а уж описать все ОС, входящие в это семейство просто невозможно. Тем не менее, мы, ни в коей мере не претендуя на полноту, попытаемся дать беглый обзор "мира Unix" в тех его областях, которые представляются нам интересными для целей нашего учебного курса.

Рождение ОС Unix относится к концу 60-х годов, и эта история уже обросла "легендами", которые подчас по-разному повествуют о деталях этого события. ОС Unix родилась в исследовательском центре Bell Telephone Laboratories (Bell Labs), входящем в состав корпорации AT&T. Изначально этот инициативный проект для ЭВМ PDP-7 (впоследствии - для PDP-11) представлял собой то ли с файловую систему, то ли компьютерную игру, то ли систему подготовки текстов, то ли и то, и другое, и третье. Важно, однако, то, что с самого начала проект, превратившийся в итоге в ОС, задумывался как программная среда коллективного пользования. Автором первой версии Unix является Кен Томпсон, однако в обсуждении проекта, а впоследствии - и в его реализации принимал участие большой коллектив сотрудников (Д.Ритчи, Б.Керниган, Р.Пайк и другие). На наш взгляд, несколько счастливых обстоятельств рождения Unix определили удачу этой системы на много лет вперед.

Для большинства сотрудников того коллектива, в котором родилась ОС Unix, эта ОС была "третьей системой". Существует мнение (см., например [1]), что системный программист достигает высокой квалификации только при выполнении третьего своего проекта: первый проект получается еще "ученическим", во второй разработчик пытается включить все, что не получилось в первом, и в итоге он получается слишком громоздким, и только в третьем достигается необходимый баланс желаний и возможностей. Известно, что до рождения Unix коллектив Bell Labs участвовал (совместно с рядом других фирм) в разработке ОС MULTICS. Конечный продукт MULTICS (Bell Labs не принимала участия в последних стадиях разработки) носит все признаки "второй системы" и не получил широкого распространения. Следует, однако, заметить, что в этом проекте были рождены многие принципиально важные идеи и решения, и некоторые концепции, которые многие считают рожденными в Unix, на самом деле имеет своим источником проект MULTICS.

ОС Unix была системой, которая делалась "для себя и для своих друзей". Перед Unix не ставилась задача захвата рынка и конкуренции с какими-либо продуктами. Сами разработчики ОС Unix были и ее пользователями, и сами оценивали соответствие системы своим нуждам. Без давления рыночной конъюнктуры такая оценка могла быть предельно объективной.

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

В 1972-73 гг. Кен Томпсон и Деннис Ритчи написали новую версию Unix. Специально для этой цели Д.Ритчи создал язык программирования C, представлять который теперь уже нет необходимости. Более 90% программного кода Unix написано на этом языке, и язык стал неотъемлемой частью ОС. То, что основная часть ОС написана на языке высокого уровня, обеспечивает возможность ее перекомпиляции в коды любой аппаратной платформы и является обстоятельством, определившим широкое распространение Unix.

В период создания Unix антимонопольное законодательство США не давало корпорации AT&T возможности выходить на рынок программных продуктов. Поэтому ОС Unix была некоммерческой и свободно распространялась, прежде всего - в университетах. Там ее развитие продолжалось, и наиболее активно оно велось в Калифорнийском университете в г.Беркли. При этом университете была создана группа Berkeley Software Distribution, которая занималась развитием отдельной ветви ОС - BSD Unix. На протяжении всей последующей истории основная ветвь Unix и BSD Unix развивались параллельно, неоднократно взаимно обогащая друг друга.

По мере распространения ОС Unix стал все более возрастать интерес к ней коммерческих фирм, которые стали выпускать собственные коммерческие версии этой ОС. Со временем стала коммерческой и "основная" ветвь Unix от AT&T, для ее продвижения была создана дочерняя фирма Unix System Laboratory. Ветвь BSD Unix в свою очередь разветвилась на коммерческую BSD и Free BSD [18]. Различные коммерческие и свободно распространяемые Unix-подобные системы строились на базе ядра AT&T Unix, однако в них включались и свойства, заимствуемые из BSD Unix, а также и оригинальные свойства. Несмотря на общий источник, различия между членами семейства Unix накапливались и в итоге привели к тому, что перенос приложений из одной Unix-подобной ОС в другую стал чрезвычайно затруднен. По инициативе пользователей Unix возникло движение за стандартизацию API Unix. Это движение было поддержано Международной организацией стандартов ISO и привело к возникновению стандарта POSIX (Portable Operation System Interface eXecution), который развивается и в настоящее время и является самым авторитетным стандартом для ОС. Однако, оформление спецификаций POSIX как официального стандарта - процесс довольно медленный, и он не может удовлетворять потребностей производителей программного обеспечения, что привело к возникновению альтернативных промышленных стандартов.

С переходом AT&T Unix к компании Nowell название этой ОС изменилось на Unixware, а права на торговую марку Unix перешли к консорциуму X/Open. Этот консорциум (в настоящее время - Open Group) разработал свои (более широкие, чем POSIX) спецификации системы, известные как Single Unix Specification. Недавно вышла вторая редакция этого стандарта, значительно лучше согласованная с POSIX.

Наконец, ряд фирм - производителей собственных версий Unix образовал консорциума Open Software Foundation (OSF), который выпустил собственную версию Unix - OSF/1, сделанную на базе микроядра Mach. OSF также выпустил спецификации системы OSF/1, на основе которой фирмы-члены OSF стали выпускать собственные Unix-системы. Среди таких систем: SunOS фирмы Sun Microsystems, AIX фирмы IBM, HP/UX фирмы Hewlett-Packard, DIGITAL UNIX фирмы Compaq и другие.

Поначалу Unix-системы этих фирм в большей степени базировались на BSD Unix, но сейчас большая часть современных промышленных Unix-систем строятся на базе использовании (по лицензии) ядра AT&T Unix System V Release 4 (S5R4), хотя наследуют и некоторые свойства BSD Unix. Мы не берем на себя ответственность сравнивать коммерческие Unix-системы, так как периодически появляющиеся в печати сравнения такого рода зачастую представляют совершенно противоположные результаты.

Компания Nowell продала Unix компании Santa Crouse Operations, которая выпускала собственный Unix-продукт - SCO Open Server. SCO Open Server [16] базировался на более ранней версии ядра (System V Release 3), но был великолепно отлажен и отличался высокой стабильностью. Фирма Santa Crouse Operations интегрировала свой продукт с AT&T Unix и выпустила Open Unix 8 [30], однако затем продала Unix фирме Caldera, которая и является владельцем "классической" ОС Unix сегодня (в конце 2001 г.).

Фирма Sun Microsystems начала свое представительство в мире Unix системой SunOS, созданной на основе ядра BSD. Однако впоследствии заменила ее системой Solaris на основе S5R4 [34]. В настоящее время распространяется версия 8 этой ОС (существует также v.9-бета). Solaris работает на платформе SPARC (RISC-процессоры, изготовляемые по спецификациям Sun) и Intel-Pentium.

Фирма Hewlett-Packard предлагает ОС HP-UX.v.11 на платформе PA-RISC [22]. HP-UX базируется на S5R4, но содержит много свойств, "выдающих" ее происхождение от BSD Unix. Конечно же, HP-UX будет доступна и на платформе Intel-Itanium.

Фирма IBM выступает с ОС AIX, последняя на сегодняшний день версия - 5L (о ней еще пойдет речь впереди) [12]. IBM не объявляла "родословную" AIX, это в основном оригинальная разработка, но первые версии носили признаки происхождения от FreeBSD Unix. Сейчас, однако, AIX больше похожа на S5R4. Первоначально ОС AIX была доступна и на платформе Intel-Pentium, но впоследствии (в соответствии с общей политикой IBM) перестала поддерживаться на этой платформе. В настоящее время AIX работает на серверах IBM RS/6000 и в других вычислительных платформах на базе процессоров PowerPC (в том числе и на суперкомпьютерах IBM).

ОС DIGITAL UNIX фирмы DEC была единственной промышленной реализаций системы OSF/1. ОС DIGITAL UNIX работала на RISC-серверах Alpha фирмы DEC. Когда в 1998 г. фирма DEC была поглощена фирмой Compaq, в фирму Compaq перешли и серверы Alpha, и DIGITAL UNIX. Фирма Compaq имеет намерение восстановить присутствие на рынке серверов Alpha и в связи с этим интенсивно развивает и ОС для них. Нынешнее название этой ОС - Tru64 Unix (текущая версия - 5.1A), она продолжает базироваться на ядре OSF/1 и несет в себе много признаков BSD Unix [37].

Несмотря на то, что большинство коммерческих Unix-систем базируется на одном ядре и удовлетворяет требованиям POSIX, каждая из них имеет собственный диалект API, и различия между диалектами накапливаются. Это приводит к тому, что перенос промышленных приложений с одной Unix-системы на другую затрудняется и требует, как минимум, перекомпиляции, а часто - и корректировки исходного кода. Попытка преодолеть "разброд" и сделать единую для всех ОС Unix была предпринята в 1998 г. альянсом фирм SCO, IBM и Sequent. Эти фирмы объединились в проекте Monterey с целью создания единой ОС на базе Unixware, владельцем которой в то время была SCO, IBM AIX и ОС DYNIX фирмы Sequent. (Фирма Sequent занимает лидирующие позиции в производстве ЭВМ архитектуры NUMA - несимметричной многопроцессорной - и DYNIX - это Unix для таких ЭВМ). ОС Monterey должна была работать на 32-разрядной платформе Intel-Pentium, 64-разрядной платформе PowerPC и на новой 64-разрядной платформе Intel-Itanium. О поддержке проекта заявили почти все лидеры производства аппаратных средств и промежуточного программного обеспечения. Даже фирмы, имеющие собственные клоны Unix (кроме Sun Microsystems), объявили, что на платформах Intel они будут поддерживать только Monterey. Работа над проектом продвигалась, по-видимому, успешно. ОС Monterey была в числе первых, доказавших свою работоспособность на Intel-Itanium (наряду с Windows NT и Linux) и единственной, которая при этом не прибегала к эмуляции 32-разрядной архитектуры Intel-Pentium. Однако в финальной стадии проекта произошло фатальное событие: SCO продала свое Unix-отделение. Еще раньше фирма Sequent вошла в состав IBM. "Наследником" всех свойств ОС Monterey стала ОС IBM AIX v.5L. Однако, не совсем всех. Платформа Intel-Pentium не является для IBM стратегическим направлением, и на этой платформе ОС AIX недоступна. А поскольку другие лидеры компьютерной индустрии не разделяют (или не вполне разделяют) такую позицию IBM, идея общей ОС Unix так и не реализовалась.

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

Последние годы отмечены шумной экспансией ОС Linux [9, 26]. Ядро этой ОС было разработано в 1991 Линусом Торвальдсом (Финляндия) прежде всего "для личного пользования". Торвальдс сделал исходный код своей ОС открытым. При фиксированном ядре любой программист может написать собственные сервисы ОС Linux и опубликовать их через Internet. Трудно сказать, что послужило причиной такой популярности ОС Linux. Она не является ни уникальной, ни лучшей ни как свободно распространяемая, ни как открытая, ни как Unix для компьютеров небольшой вычислительной мощности. По-видимому, этот феномен объясняется некоторым совпадением объективных и субъективных факторов, анализ которых не входит в наши цели.

До 1997 г. ОС Linux была популярна почти исключительно в университетской среде. Однако в 1997 г. ряд фирм объявил о выпуске собственных версий Linux. Некоторые из этих версий (например, Red Hat) остались бесплатными, некоторые (например, Caldera) стали коммерческими. Принципиально важно то, что у Linux появились "хозяева", которые несли ответственность (в том числе и коммерческую) за сопровождение ОС. Это вызвало стремительное возрастание интереса к Linux пользователей, которые решают задачи промышленной обработки информации. Такой интерес объясняется, с одной стороны, желанием иметь "почти настоящую" ОС Unix со значительно меньшими расходами, с другой, нежеланием попадать в полную зависимость от Microsoft. Фирмы-лидеры информационных технологий не могли игнорировать настроения рынка и объявили либо о выпуске собственных версий Linux (например, Hewlett-Packard), либо о поддержке определенных версий Linux на своих аппаратных платформах и в своем промежуточном программном обеспечении (например, IBM). Интересно, что эти фирмы являются производителем собственных коммерческих версий ОС Unix. В последних версиях всех коммерческих ОС Unix, рассмотренных выше, в API ОС внесены системные вызовы, обеспечивающие возможность выполнения в них приложений, написанных для Linux. Пока, по-видимому, гранды информационных технологий не видят в Linux серьезного конкурента для своих ОС в сфере промышленной обработки данных и систем высокой готовности и предусматривают перенос информационных систем с Linux на коммерческие Unix при достижении ими определенной степени зрелости. Не без помощи "грандов" достигнут перенос Linux на большое число платформ - от встроенных вычислительных устройств до мейнфреймов и суперкомпьютеров. Возможно, с достижением Linux промышленного уровня, в этой ОС сможет воплотиться идея, не удавшаяся в проекте Monterey - единая ОС Unix для всех.

Следует отметить еще одну интересную сферу применения Linux. Ряд стран (например, Китай, Россия) объявил о принятии в качестве базовой ОС для информационных системах в своих силовых структурах ОС, "изготовляемой на основе Linux". Основную роль здесь играет открытость исходного кода. Доступность исходного кода Linux позволяет правительственным специалистам этих стран с одной стороны убедиться в отсутствии в ОС "закладок", занимающихся "электронным шпионажем", а с другой - провести исчерпывающую верификацию ОС и добиться ее высокой надежности и безопасности.

В следующем изложении мы ориентируемся прежде всего на "классическую" ОС Unix, ведущую свою родословную от Bell Labs, и ее последнюю на сегодняшний день версию - Open Unix 8, но рассматриваем также и некоторые особенности других коммерческих и некоммерческих ОС семейства Unix.

6.2. Архитектура Unix

Архитектура ОС Unix [14] представлена на рисунке 6.1.


Рисунок 6.1 Архитектура Unix

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

Модули первой части пишутся на языке Ассемблера целевой платформы и выполняют:

Модули второй части написаны на языке C и обеспечивают высокоуровневую обработку, в том числе:

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

6.3. Процессы

Концепция процесса в том виде, в каком она представлена в нашей книге, родилась именно в MULTICS и Unix. Процессом является выполняемая программа, которая представляет собой последовательности байтов, интерпретируемые процессором как машинные команды, данные и стековые структуры.

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

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

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

Контекст процесса состоит из пользовательской и системной составляющих.

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

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

Статическая часть системного контекста процесса включает в себя:

Динамическая часть системного контекста процесса представляет собой стек ядра.

Стек, входящий в состав пользовательской части контекста процесса, предназначается для размещения в нем локальных переменных и обеспечения возвратов из вложенных вызовов процедур. Однако, как мы сказали выше, процесс может выполняться как в режиме процесса, так и в режиме ядра (точнее - модули ядра выполняются в контексте процесса). Динамическая часть системного процесса предназначена для обеспечения функционирования в режиме ядра. Выполнение модулей в режиме ядра может прерываться так же, как и выполнение модулей в режиме процесса. ОС Unix рассчитана на некоторую иерархию прерываний: каждое прерывание имеет некоторый уровень приоритета, и обработка прерывания какого-то уровня может быть прервано прерыванием с более высоким уровнем приоритета. Уровни приоритетов прерываний обычно поддерживаются аппаратной платформой. Типовое распределение уровней приоритетов (в порядке возрастания) следующее:

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

6.4. Нити

Нити появились в Unix довольно поздно, но они вошли в требования стандартов POSIX и Single Unix Specifications. Во всех современных клонах ОС Unix имеется механизм нитей, семантика (но не обязательно синтаксис) которого соответствует требованиям стандарта POSIX. В Open Unix 8 реализация нитей выполнена на уровне системной библиотеки нитей, однако потребовала и серьезной перестройки ядра. На уровне ядра работа с нитями поддерживается системными сущностями, называемыми легковесными процессами (light weight process). Нить представляет собой отдельный поток управления с точки зрения программы. Легковесный процесс - отдельный поток управления с точки зрения ОС. Легковесный процесс предоставляет нити собственную среду выполнения, прежде всего - динамическую составляющую системного процесса, то есть стек ядра. Легковесные процессы могут интерпретироваться как виртуальные процессоры, как показано на рисунке 6.2. В каждый момент времени легковесный процесс может выполнять только одну нить, но нити могут сменять друг друга в легковесном процессе.


Рисунок 6.2 Нити и легковесные процессы (ЛВП)

Легковесные процессы подчиняются следующим правилам:

Нити могут быть мультиплексируемыми и связанными.

Системная библиотека нитей обеспечивает мультиплексирование нитей в пуле легковесных процессов каждого процесса по следующим правилам:

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

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

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

Приоритеты нитей статические. Изначально созданная нить наследует приоритет нити, ее породившей, но приоритет может быть изменен явным образом при помощи системного вызова.

Приведенное выше описание механизма нитей мы строили на базе ОС Open Unix 8. Подобным же образом этот механизм реализован в ОС Solaris 8. В ОС AIX 5L "легковесные процессы" называются "нитями ядра". В этих ОС также различаются связанные и мультиплексируемые нити.

Однако, ряд клонов реализуют совершенно иной механизм нитей. В ОС FreeBSD нити фактически являются отдельными процессами. В ОС FreeBSD имеется системный вызов rfork, который порождает новый процесс с возможностью управления наследованием ресурсов в новом процессе. Среди ресурсов, определяемых для наследования, может быть и адресное пространство процесса-родителя. Библиотечный вызов rfork_thread позволяет создать на базе вызова rfork нить и запустить в ней заданную процедуру.

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

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

В ОС Tru64 Unix имеется вызов pthread_atfork(), который позволяет определить процедуру, выполняемую в процессе, порождаемом системным вызовом fork().

Помимо пользовательских нитей, почти во всех описанных нами ОС бывают еще нити ядра, порождаемые с помощью вызова kernel_thread() для внутренних системных нужд.

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

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

Состояния процессов, которые различаются в ОС Unix, показаны на рисунке 6.3.


Рисунок 6.3 Состояния процесса в ОС Unix

Новый процесс создается системным вызовом fork (см. ниже) - переход 1 на рисунке 6.3. Если оперативной памяти в системе достаточно, то процесс создается в памяти (выделяется память для размещения адресного пространства процесса) - переход 2. Если памяти недостаточно (только в системе с подкачкой сегментов), то процесс создается на внешней памяти - переход 3. Если процесс создан в памяти, он переходит в состояние готовности к выполнению, из которого может быть запущен на выполнение - переход 4. При запуске процесс начинает выполнение в режиме ядра, но затем "возвращается" (такова специфика выполнения системного вызова fork) в режим задачи - переход 5. Выполняемый в режиме задачи процесс может перейти в режим ядра по внешнему прерыванию или выдав системный вызов (программное прерывание) - переход 6. Выполнение обработчика прерывания или системного вызова происходит в режиме ядра, но в контексте процесса. Выполнение в режиме ядра может прерываться, как было описано выше, но с возвратом в прерванный уровень - переход 7. Если переход в режим ядра произошел по причине прерывания от таймера, и планировщик процессов ОС принимает решение о том, что необходимо запустить другой процесс, то процесс переходит в зарезервированное состояние - переход 8. Зарезервированное состояние в принципе идентично состоянию готовности в памяти, различие между ними состоит в том, что выполнение зарезервированного процесса (когда до него дойдет очередь) возобновляется сразу в режиме задачи - переход 9. Если же переход в режим ядра произошел в связи с выполнением, а это выполнение связано с необходимостью ожидания или планировщик процессов ОС принимает решение о том, что необходимо запустить другой процесс, то процесс переходит в состояние приостановки - переход 10. Когда процесс получит те ресурсы, которых он ожидает, он переводится в состояние готовности - переход 11, из которого он может быть вновь запущен в режиме ядра - переход 4, а из него вернуться в выполнение в состоянии задачи - переход 5. При нехватке памяти приостановленный или даже готовый процесс может быть выгружен на внешнюю память - переходы 12. Процесс, ожидающий ресурса на внешней памяти, там же на внешней памяти может быть переведен в состояние готовности - переход 11. Готовый процесс на внешней памяти (перешедший в состояние готовности из приостановки или созданный на внешней памяти) загружается (подкачивается) в память - переход 13. Когда выполнение процесса завершается (выполнением системного вызова exit), процесс переходит в режим ядра, а из него - в состояние завершения - переход 14. В этом состоянии большинство ресурсов процесса освобождается, но строка в таблице процессов остается, в ней сохраняется некоторая информация о процессе, которая может быть "востребована" и после завершения процесса, например, код завершения процесса.

С самого начала "проект Unix" задумывался как система с разделением времени. Исходная дисциплина планирования процессов, называемая иногда "алгоритмом полураспада", описана нами в разделе 2.3 части I. Там мы, однако, рассматривали только динамическое перевычисление приоритетов и не упомянули о том, что в системе имеются два класса процессов: процессы ядра и пользовательские процессы. Планирование по "алгоритму полураспада" выполняется только для пользовательских процессов. Системные же процессы имеют более высокие приоритеты, и их приоритеты заложены в коде ядра. Так, наивысший приоритет имеет процесс подкачки страниц, следующий - процесс ожидания дискового ввода-вывода и т.д. Даже когда пользовательский процесс выполняется в режиме ядра, он не становится процессом ядра, и никакие динамические добавки к приоритету не могут вывести приоритет пользовательского процесса за тот порог, который разделяет процессы ядра и процессы пользователей. Приоритеты процессов ядра абсолютные: появление процесса ядра, готового к выполнению, прерывает выполнение пользовательского процесса или менее приоритетного процесса ядра.

Дисциплина "алгоритма полураспада" обеспечивает прекрасные показатели справедливости обслуживания, что делает ее удобной для интерактивной работы, но непригодной для выполнения процессов реального времени. Стандарты POSIX и Single Unix Specifications требуют наряду с обеспечением интерактивной работы и обеспечения реального времени. Поэтому в современные клонах ОС Unix дисциплина планирования несколько модифицирована. В системе теперь различаются три класса процессов (в порядке возрастания приоритетов):

Процессы разделения времени - аналогичны пользовательским процессам в "старой" ОС Unix. Но цели их планирования несколько изменились. Теперь наряду с обеспечением приемлемого времени реакции для интерактивных процессов, дисциплина должна обеспечивать также и хорошую производительность для "счетных" процессов. Для этого алгоритм планирования процессов разделения времени модифицирован изменением размера кванта времени. Для процессов с низким приоритетом размер кванта увеличивается. В соответствии с правилами динамического перевычисления приоритеты тех процессов, которые переходят в состояние приостанова, не исчерпав полученного кванта, повышаются, а тех, которые используют выделенный им квант до конца - понижаются. Это приводит к селекции процессов: интерактивные процессы получают высокие приоритеты, а счетные - низкие. В результате счетный процесс получает квант времени ЦП реже, чем интерактивный, но размер этого кванта для счетного процесса больше.

Процессы ядра - те же, что и в "старой" ОС Unix, и планируются они так же.

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

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

Основные системные вызовы, обеспечивающие порождение процессов в Unix, описаны нами в разделе 4.3 части I, это:

Аналогичные системные вызовы в отношении нитей:

6.6. Управление памятью

Традиционно API Unix представляет сегментную модель памяти. Каждому процессу при создании выделяется три сегмента: сегмент кодов, сегмент данных и сегмент стека. Процесс может изменять размер выделенного ему сегмента, а также получать сегменты разделяемой памяти и управлять ими.

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

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

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

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

Список абсолютно свободных страниц, то есть страниц, не включенных в адресное пространство никакого процесса.

Список "условно свободных" страниц, то есть страниц, которые являются кандидатами на вытеснение, элементы этого списка входят также в один из вышеназванных списков.

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


Рисунок 6.4 Логическая структура управления адресным пространством процесса

Представленная на рисунке 6.4 структура управления адресным пространством процесса является логической концепцией, реализация ее на разных аппаратных платформах может существенно различаться. Так, в Open Unix и в других клонах на платформе Intel-Pentium сегментная структура адресного пространства является лишь оболочкой, обеспечиваемой программным окружением, а не ОС. На самом же деле адресное пространство процесса здесь представляет собой просто массив страниц. Сегменты являются только группами страниц, а представляются для процесса в виде традиционных для Unix сегментов только модулями библиотеки системных вызовов.

В реализациях Unix на страничной (или сегментно-страничной) аппаратной платформе свопинг ведется на уровне страниц. Используется концепция "возраста" страницы, представляющая собой один из вариантов дисциплины LRU. В дескрипторе каждой виртуальной страницы имеется число - ее возраст. ОС ведет список свободных ("условно свободных") страниц в массиве дескрипторов страничных фреймов и в конфигурационных параметрах устанавливается два числа: верхний и нижний пределы размера этого списка. Поддержанием списка свободных страниц в требуемом состоянии занимается системный процесс - сборщик страниц. При возникновении страничных отказов сборщик страниц проверяет и очищает биты использования всех страниц в реальной памяти. Если в промежутке между двумя такими проверками к странице не было обращений (бит использования страницы остался нулевым), то возраст этой страницы увеличивается. Если размер списка свободных страниц достигает нижнего предела, сборщик страниц пополняет его теми страницами, возраст которых наибольший. При этом он доводит размер списка до верхнего предела. Страничный кадр, попавший в список "условно свободных" не сразу распределяется для размещения в нем другой виртуальной страницы. Если до нового распределения к нему будет обращение, то он будет исключен из списка свободных кадров. В последних реализациях Unix алгоритм сборки страниц упрощается: в качестве возраста используется единственный бит - бит использования, а проверка и сброс его производится периодически.

Ранние версии Unix поддерживали две модели свопинга - подкачку страниц (описанную выше) и подкачку процессов. Вторая модель, исторически появившаяся первой, была ориентирована на сегментную модель динамической трансляции адресов в аппаратуре, но вытеснялся при этом весь процесс, всеми своими сегментами. Состояния процесса "приостановлен, вытеснен" и "готов, вытеснен" на рисунке 6.3. связаны именно с моделью подкачки процессов. При повсеместном внедрении аппаратных платформ с сегментно-страничной аппаратной трансляцией адресов произошел отказ от подкачки процессов и свопинг ограничился только страничным уровнем. Однако в дальнейшем подкачка процессов была совмещена с подкачкой страниц. Так, в Open Unix при нормальной загрузке свопинг осуществляется только на страничном уровне. Однако при существенной нехватке памяти процесс может быть вытеснен целиком, всеми своими страницами. Таким образом, состояния "приостановлен, вытеснен" и "готов, вытеснен" продолжают оставаться актуальными.

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

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

paddr=mmap(addr,len,prot,flags,fd,off); 
где addr - "заказываемый" виртуальный адрес сегмента в адресном пространстве процесса (возвращаемое значение может и не совпадать с ним), len - размер сегмента, prot - возможности доступа, flags - управляющие флаги, fd - манипулятор файла или другого объекта, off - смещение в файле.

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

Механизм отображения в память в Open Unix заменяет старые средства управления памятью. Хотя традиционные системные вызовы управления памятью здесь тоже сохраняются, но они обеспечиваются только библиотекой системных вызовов, которая преобразует их в отображение в память. Механизм отображения в память позволяет процессам также получать дополнительные частные сегменты в адресном пространстве процессе. Отображение в память "файла" с именем "/dev/zero" дает процессу частный сегмент запрошенного размера.

Выполнение системного вызова fork в традиционной ОС Unix подразумевает откладывание выделения для процесса-потомка отдельных частных сегментов. Вместо этого применяется политика "копирования при записи": два процесса - предок и потомок - разделяют один сегмент, но этот сегмент помечается как защищенный от записи. Пока ни один из процессов не изменяет содержимого сегмента, процессы используют один и тот же сегмент. Когда один из процессов пытается писать в сегмент, происходит исключение, обрабатывая которое ОС создает копию сегмента для процесса-потомка, и с этого момента каждый процесс использует свой собственный сегмент. В Open Unix политика "копирования при записи" реализуется на уровне страниц.

Динамическая компоновка в современных Unix в принципе идентична таковой во многих других современных ОС (OS/2, Windows 9x, Windows NT). Модули динамической компоновки называются здесь разделяемыми объектами (shared object). Они представляют собой программные модули, содержащие несколько входных точек. Библиотека разделяемых объектов, однако, содержат не один такой модуль, а целый набор их. При загрузке или при выполнении кодовый сегмент разделяемого объекта включается в адресное пространство процесса. Код разделяемого объекта совместно используется всеми процессами, но отображается в общем случае в разные участки виртуальной памяти разных процессов. Разделяемые объекты, таким образом, компилируются и компонуются так, чтобы они могли быть перемещаемыми в виртуальном адресном пространстве. Для переменных разделяемого объекта создается отдельная область для каждого процесса, использующего объект.

6.7. Средства взаимодействия процессов

Все средства взаимодействия процессов, описанные нами в главе 9 части I, обеспечиваются в ОС Unix.

Программные каналы являются средством обеспечения взаимодействия между процессами. В старых реализациях Unix обеспечивались классические межпрограммные каналы, неименованные и именованные, описанные в разделе 9.6 части I. В новых версиях базовый интерфейс каналов остался тем же, но их внутренние механизмы изменились. Теперь программные каналы называются базирующимися на потоках и при создании канала создаются два разнонаправленных потока, по которым данные движутся по правилам FIFO.

Сигналы в Unix являются не столько средством взаимодействия между процессами, сколько средством взаимодействия между ядром и процессами. Сигналы посылаются ядром процессу, чтобы сообщить процессу о некотором событии, чаще всего представляющем собой возникновение некоторой нештатной ситуации. В Open Unix имеется 31 тип сигналов, которые можно разделить на группы:

Разделяемые области памяти являются весьма широко применяемым средством обмена данными между процессами. Один процесс создает разделяемую область памяти при помощи системного вызова shmget, другие - присоединяют область памяти к своему виртуальному адресному пространству при помощи системного вызова shmat.

Набор семафоров в Unix представляет собой множество традиционных общих семафоров, число которых задается при создании набора семафоров в системном вызове semget. Процесс, создавший набор семафоров, может выполнять над ним любые операции, и он определяет права управления любым семафором из набора (при помощи системного вызова semctl) для других процессов, использующих семафор. Каждый отдельный семафор состоит из следующих элементов:

Выполнение собственно семафорных операций над любым семафором из набора обеспечивается системным вызовом semop. Возможные операции над семафором:

Очереди сообщений в Unix полностью совпадают с очередями, описанными нами в разделе 9.7 части I. Тела сообщений сохраняются в адресном пространстве ядра. Заголовки сообщений в очереди составляют связный список, каждый элемент которого содержит:

Каждая очередь описывается структурой, содержащей:

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

Замок взаимного исключения (mutual exclusion lock). Операции установки замка и снятия замка идентичны скобкам критической секции.

Зацикленный замок (spin lock) - аналогичен простому замку, но вместо ожидания в приостановке обеспечивает занятое ожидание. Такие замки защищают нить от вытеснения с легковесного процесса при ожидании на замке.

Рекурсивный замок (recursive lock) - аналогичен простому замку, но исключает самоблокирование нити при рекурсивном входе в критическую секцию.

Замок чтения-записи (reader-writer lock) - обеспечивает нахождение в критической секции в каждый момент времени не более одной нити-"писателя" и любого числа нитей-"читателей".

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

Барьер - средство, обратное замкам. Барьер создает "критическую секцию", в которую может войти только заданное количество нитей одновременно.

Переменная условия (condition variable) - аналог событий. Обеспечивает перевод нити в ожидания до тех пор, пока эта переменная не будет установлена в другой нити.

При освобождении нитей, ожидающих на средствах синхронизации, применяются следующие правила:

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

6.8. Файловые системы

Базовой единицей, в которую Unix записывает информацию, является файл. Файл - это именованное собрание данных, которое является единицей хранения данных. Файлы записываются в область памяти на одном или нескольких дисках, которая называется файловой системой. Файловая система разделяется на меньшие области памяти, которые называются каталогами. Каталоги могут включать в себя файлы и другие каталоги и образуют иерархическую структуру с общим корнем. В отличие от ряда других ОС (MS DOS, OS/2, все Windows) в единое дерево каталогов в Unix включаются все тома дисковых носителей.

Корневым каталогом является каталог с именем "/". В этом каталоге находятся файлы, используемые при загрузке системы и другие каталоги. Некоторые каталоги в корневом каталоге создаются при инсталляции системы. Среди этих каталогов:

Каждый том представляет собой отдельную файловую систему со своим деревом каталогов. При работе с несколькими томами файловая система каждого тома подключается (монтируется) к общей файловой системе в виде ветви общего дерева каталогов. Монтирование не обязательно производится к корню общей файловой системы.

OC Unix обеспечивает также те средства, которые мы в главе 7 части I описали как алиасы и косвенные файлы. Алиасы - в Unix они называются жесткими связями (hard link) или просто связями - представляют собой две или более ссылок на один и тот же физический файл из разных каталогов (или из одного каталога, но под разными именами). Они легко обеспечиваются в ОС Unix за счет того, что в большинстве файловых систем Unix (см. ниже) дескриптор физического файла и элемент каталога хранятся раздельно. Косвенные файлы в Unix называются символическими связями (symbolic link). Физически символическая связь представляет собой специальный файл.

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

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

Файловая система s5 была исторически первой файловой системой в Unix. Структура тома в файловой системе s5 показана на рисунке 6.5.


Рисунок 6.5 Структура тома в файловой системе s5

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

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

Также в суперблоке имеется массив из 50 номеров свободных логических блоков в области данных. Последний элемент этого массива адресует логический блок, в котором находится продоолжение списка свободных блоков, а последний элемент в нем в нем - блок с продолжением списка и т.д.

Файловые индексы в Unix представляют собой то, что мы в главе 7 части I называли дескриптором файла. Оригинальное название такого индекса - inode. В файловой системе s5 дескрипторы отделены от элементов каталогов. Файловый индекс содержит информацию о физическом файле, а именно:

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

Файловый индекс не содержит имени файла - оно содержится в элементе каталога. Максимальное число файловых индексов, возможное на томе s5 - 65500

План размещения файла в s5 описан нами в разделе 7.6 части I, он представляет собой несбалансированное дерево с прямой адресацией к начальной части файла и одно-, двух- и трехуровневой адресацией к следующим частям. Отметим, что в современных версиях файловой системы s5 единицей распределения дискового пространства является не физический блок размером 512 байт, а логический блок, размер которого может выбираться из ряда 512, 1024, 2048 байт.

В области данных располагаются файлы и каталоги.

Каталоги s5 состоят из 16-байтных элементов, в которых первые 2 байта - номер индекса в массиве файловых индексов, а еще 14 байт - имя файла.

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

Файловая система ufs пришла из BSD Unix и имеет ряд существенных отличий от s5. Первое отличие состоит в том, что пространство диска в ufs разбивается на участки одинакового размера, называемые группами цилиндров, и управляющие структуры распределены по группам цилиндров, как показано на рисунке 6.6.


Рисунок 6.6 Структура тома в файловой системе ufs

Загрузочный (его размер - 8 Кбайт) блок присутствует только в первой группе цилиндров. В каждой группе цилиндров имеется копия суперблока. При нормальной работе используется только суперблок из первой группы цилиндров, остальные копии служат для восстановления суперблока в случае порчи оригинала.

В суперблоке ufs содержится:

Карта группы цилиндров содержит информацию о состоянии (занят/свободен) логических блоков в области данных.

Назначение массива файловых индексов в ufs - такое же, как и в s5, но массив каждой группы цилиндров относится только к файлам данной группы. В файловом индексе ufs содержится:

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

Размер логического блока выбирается из ряда: 2, 4, 8 Кбайт. Поскольку большой размер блока может приводить к появлению значительных внутренних дыр, допускается разбиение блока на фрагменты. Размер фрагмента может быть 512, 1024, 2048 или 4096 байт. Фрагментированные блоки используются для хранения "остатков" нескольких файлов в одном блоке.

Файловая система ufs позволяет также устанавливать для пользователей квоты на использование двух основных ресурсов файловой системы: файловых индексов и блоков данных. Первый лимит ограничивает количество файлов, создаваемых пользователем, второй - общий объем дисковой памяти для пользователя. Квоты могут быть установлены "жесткие" или "мягкие". Лимиты "жесткой" квоты не могут быть превышены ни при каких обстоятельствах. Лимиты "мягкой" квоты могут быть превышены, но не более, чем на заданный интервал времени.

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

Файловая система sfs является вариантом системы ufs. Ее отличие состоит в том, что для каждого файла создается два файловых индекса:

Элемент каталога sfs содержит ссылку только на четный индекс, поэтому программы, работающие с файловыми индексами, "видят" только четный индекс.

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

Файловую систему vxfs называют также Veritas - по названию фирмы, выпускающей этот продукт. Достоинствами vxfs являются:

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

Все эти операции должны выполняться как одна транзакция - или выполниться все до конца, или не выполняться вообще. Список намерений представляет собой циклически используемый список. По умолчанию для этого списка выделяется 512 блоков. Любое изменение в структуре файловой системы разбивается на список подопераций, и в список намерений заносится запись о транзакции с указанием в ней всех составляющих подопераций. vxfs поддерживает список для всех незавершенных транзакций файловой системы. Запись заносится в список намерений до выполнения входящих в транзакцию подопераций. После того, как запись списка намерений сохранена на диске, подоперации транзакции могут выполняться с любой задержкой. При восстановлении после сбоя системы утилита fsck просматривает список намерений и либо завершает, либо откатывает те операции, которые выполнялись во время сбоя.

Логический блок (единица распределения памяти) в vxfs может иметь размер 1, 2, 4, 8 Кбайт. Память для файлов распределяется экстентами - участками, состоящими из одного или более логических блоков. Элемент плана размещения файла содержит две составляющих: номер первого блока в экстенте и размер экстента. План размещения файла в vxfs содержит массив, в котором первые 10 элементов являются прямыми описателям первых экстентов файла, 11-й элемент описывает экстент (по умолчанию размер этого экстента - 8 Кбайт), который используется для косвенной адресации следующих экстентов, 12-й элемент описывает экстент, который используется для двухуровневой косвенной адресации следующих экстентов.

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

В настоящее время vxfs поддерживается в версиях 1, 2 и 4. Между версией 1 и последующими есть принципиальная разница, поэтому сначала изложим основные свойства версии 1.

Структура файловой системы vxfs v.1 показана на рисунке 6.7.


Рисунок 6.7 Структура файловой системы vxfs v.1

Общая для всей файловой системы информация включает в себя суперблок и описанный выше список намерений. Остальное пространство диска в vxfs v.1 разбивается на, так называемые, единицы распределения (allocation unit), смысл которых - тот же, что и групп цилиндров в ufs. В каждой единице распределения содержится:

Структура файловой системы vxfs v.2 показана на рисунке 6.8.


Рисунок 6.8 Структура файловой системы vxfs v.2

vxfs v.2 отличается прежде всего тем, что часть метаданных файловой системы хранится не в статических областях, а в, так называемых, структурных файлах, память для которых распределяется динамически, как и для обычных файлов. Информация о свободном пространстве хранится в статических структурах единиц распределения. Информация о файлах - в динамических структурах. vxfs v.2 использует концепцию файлового набора (fileset). Имеется два вида файловых наборов:

Общая для всей файловой системы статическая информация состоит из:

Доступ к динамически распределяемым структурам производится через таблицу размещения объектов. Эта таблица состоит из элементов, в каждом элементе таблицы содержится информация об одном файловом наборе, а именно:

В файле заголовка файлового набора записаны:

Массив файловых индексов расположен в структурном файле, который занимает несколько экстентов, размер каждого из которых по умолчанию составляет 8 Кбайт. Для этого файла создается копия. Структура файлового индекса - та же, что и в v.1. Файл распределения файловых индексов содержит:

Таблица текущего использования содержит оперативную информацию об использовании файлового набора. Информация в этой таблице может быть воссоздана по другим метаданным файлового набора.

Таблица счетчиков связей содержит число жестких связей для каждого файла в файловом наборе. Индексация в этой таблице совпадает с индексацией в массиве файловых индексов.

vxfs v.4 отличается от v.2 тем, что поддерживает файлы большого (до 2 Гбайт) размера и квоты на число файловых индексов и число блоков данных.

Другие файловые системы Open Unix

Кроме описанных выше, в Open Unix поддерживаются также файловые системы:

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

ОС IBM AIX работает также с файловыми системами JFS (эта файловая система перенесена также в OS/2 v.5) и JFS2.

О JFS мы расскажем вкратце, так как она во многом похожа на файловые системы, рассмотренные нами выше. Дисковая память выделяется логическими блоками, размер которых может выбираться от 512 байт до 4 Кбайт. Предусматриваются также "частично заполненные" блоки меньшего размера, в которых хранятся последние части файлов, если они слишком малы для выделения им полного блока. Файловый дескриптор содержит 8 прямых адресов блоков с данными файла и 9-й - адрес блока, через который осуществляется косвенная адресация к остальным данным файла - одноуровневая или (для очень больших файлов) двухуровневая.

Несколько более подробно рассмотрим файловую систему JFS2. Загрузочный блок JFS2 имеет размер 4 Кбайт и располагается, конечно, в первых секторах диска. Однако суперблок (его размер также 4 Кбайт) располагается со смещением 32 Кбайт от начала диска. В суперблоке содержится:

В файловой системе имеются две битовые карты, используемые для отслеживания состояния и распределения памяти:

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

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

Каждый файловый индекс имеет уникальный во всей файловой системе номер и размер 512 байт. Файловые индексы выделяются системой динамически. В каждом файловом индексе содержится:

Для небольших файлов сами данные файла содержатся во второй части файлового индекса. Для больших файлов вторая часть индекса содержит корень B+-дерева, через которое адресуются экстенты файла.

Также в B+-деревья структурированы каталоги. Элемент каталога имеет размер 512 байт и содержит имя файла и номер файлового индекса для файла. Имеющиеся в любом каталоге элементы с именами "." и ".." записаны не в элементы каталога, но хранятся в самом файловом индексе каталога.

 

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

В системе ввода-вывода различаются два типа устройств - блочные и символьные.

6.9. Интерфейсы Unix

При своем рождении ОС Unix была системой командной строки (в соответствии с тогдашним состоянием аппаратуры отображения), в значительной степени таковой она остается и в настоящее время. Это обусловлено традициями пользователей Unix, но в еще большей степени - богатыми возможностями командного языка ОС. Командный интерпретатор Unix является процессом, работающим в пользовательском режиме, поэтому он может быть легко заменен. В связи с этим командные интерпретаторы интенсивно развиваются все время существования этой ОС, и в настоящее время существует большое число командных интерпретаторов, которые, по-видимому, можно отнести к трем основным семействам:

Названные командные интерпретаторы являются базовыми, на их основе существует множество версий и вариаций. Все командные интерпретаторы ОС Unix объединяют общие основные свойства, такие как:

Легкость порождения новых процессов в Unix и наличие в системе большого числа утилит, выполняющих прежде всего обработку текстов, делают язык командного интерпретатора не только языком управления системой, но и языком обработки данных. Обязательные возможности командного интерпретатора и обязательный набор утилит Unix-систем определяются стандартом POSIX. Если командный язык не используется как язык программирования, то коды управляющих процедур (скриптов) не зависят от варианта командного языка.

Со временем, однако, у ОС Unix стали появляться и WIMP-интерфейсы. Основой для создания таких интерфейсов является система X Window, разработанная в Массачусетском технологическом институте. Система X Window строится по схеме клиент/сервер. Основой системы является процесс X-сервер, который выполняется на компьютере конечного пользователя и "знает" ту конкретную аппаратуру отображения, которая установлена на данном рабочем месте. X-сервер принимает и выполняет запросы от X-клиентов - программ, выполняющихся на этом же компьютере или на удаленном. Взаимодействие X-клиента и X-сервера управляется событиями. Событием в системе X является вывод X-клиентом информации на терминал или поступление внешнего события, которое принимается X-сервером, и о котором X-сервер сообщает X-клиенту. Описание двустороннего взаимодействия X-сервера и X-клиента и формата пакетов, которыми они обмениваются, составляет X-протокол. Транспортный уровень для X-протокола прозрачен. Если клиент и сервер находятся на одном компьютере, то для обмена между ними используются средства локального взаимодействия, если на разных - любые сетевые средства. Система X представляет собой совокупность программ и библиотек, таким образом, при разработке интерфейса программист может и не знать деталей X-протокола.

Консорциумом OSF принят в качестве стандарта для разработки графических интерфейсов пакет Motif, построенный на базе X Window. Пакет включает в себя менеджер окон, набор вспомогательных утилит, а также библиотеку классов. В пакете имеются также широкие возможности для создания новых графических классов.

В большинстве промышленных Unix-систем в настоящее время используется построенный на основе OSF/Motif интерфейс CDE (Common Desktop Environment), в ОС Linux применяется большое количество различных интерфейсных систем, наиболее популярные из которых - KDE и Gnome.

6.10. Unix-системы фирмы Caldera

Новый этап развития Unix и Linux связан с тем, что летом 2001 г. фирма Caldera, одна из ведущих фирм, предлагающих Linux, купила Unix-подразделение фирмы SCO. Из тех заявлений покупателя, которые были сделаны по этому поводу, поначалу можно было заключить (хотя явно об этом не говорилось), что фирма не собирается развивать далее Open Unix, а намерена интегрировать ее технологии в Linux. Однако, последующие действия фирмы опровергли опасения по поводу возможной "кончины" Unix.

Фирма Caldera выступает на рынке программного обеспечения прежде всего как производитель серверных операционных систем для платформы Intel и в настоящее время предлагает три операционные системы [16]:

Эти продукты Caldera охватывают спектр задач от "тонких" клиентов до корпоративных информационных систем.

Open Unix является и будет оставаться стратегическим продуктом фирмы, прежде всего потому, что даже при примерно одном уровне продаж за последние годы, он обеспечивает стабильно растущий доход. Open Unix 8 - основа для работы приложений и серверов в масштабе от рабочих станций до корпоративной информационной системы. Open Unix существует в редакциях: Base, Business, Department, Enterprise, Data Center, каждая из которых отвечает требованиям различных категорий задач (по возрастающей). Во всех редакциях существуют средства (или расширения), позволяющие обеспечить высокую устойчивость, безопасность и почти линейную масштабируемость. Open Unix 8 является ОС, ориентированной прежде всего на решения промышленного масштаба. Наиболее часто Open Unix применяется в качестве платформы для сервера баз данных или сервера электронного бизнеса (сервера приложений, ориентированного на выполнение транзакций). В частности, только на Open Unix и Unixware 7 работает Caldera ReliantHA - программное решение, обеспечивающее поддержку кластерных соединений (2 - 4 узла) с эффективным масштабированием производительности, постоянным мониторингом состояния системы и автоматическим перераспределением задач при выходе из строя одного из узлов. Использование кластерных решений с ReliantHA для Open Unix 8 позволяет повысить коэффициент готовности системы до 99.995. Open Unix будет продолжать развиваться, прежде всего - в направлении обеспечения платформы для крупномасштабных корпоративных решений.

Интересным свойством Open Unix 8 является интеграция возможностей Unix и Linux. В этой ОС могут выполняться как "родные" Unix-приложения, так и приложения для Open Linux или для других Linux-систем, соответствующие спецификациям Linux Standard Base, причем зачастую - с лучшей производительностью, чем на "родных" Linux-системах. Open Unix 8, таким образом, сочетает в себе надежность и масштабируемость Unix с простотой использования Linux. (О механизме обеспечения такой интеграции - см. ниже.)

Open Linux Server поставляется в трех конфигурациях, готовых к работе с наиболее распространенными серверными программными продуктами:

Open Linux Workstation ориентирована прежде всего на разработку и портирование приложений для Unix и Linux платформ. Включает в себя полный набор средств разработки, среди которых ведущее место занимают средства технологий Java.

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

Темпы развития ОС Unix не могут быть слишком высокими, потому что именно эта система была и остается пионером в поиске и внедрении новых технологий, и ей просто "неоткуда ждать подсказок". Темпы развития Linux могут быть сверхвысокими - в первую очередь благодаря заимствованиям из Unix. Хотя эти ОС становятся и будут становиться все более "дружественными" одна к другой, их слияние в ближайшей перспективе не произойдет. Интенсивное развитие Open Linux происходит прежде всего за счет внедрения в нее технологий Open Unix. Такое заимствование позволяет прогнозировать превращение Open Linux в действительно промышленную ОС масштаба предприятия уже в ближайшие год-два.

Open Server R5 является многофункциональной серверной ОС для выполнения широкого спектра задач среднего класса. Хотя эта ОС считается несколько устаревшей (строится на базе более ранней версии ядра, чем большинство других Unix-систем), для нее существует множество приложений, и она пока остается самой популярной Unix системой: 38% инсталляций Unix во всем мире приходится именно на эту ОС. В постсоветских странах ее доля еще выше и составляет 47.5%, причем во многих случаях продолжает эксплуатироваться версия R3. Фирма Caldera рекомендует своим пользователям мигрировать с Open Server на Open Unix, но не будет заставлять их форсировать этот процесс. Open Server будет поддерживаться и развиваться, хотя качественных скачков в развитии этой ОС ожидать уже не приходится.

Важной акцией, обеспечивающей плавную миграцию с Open Server на Open Unix, является введение в Open Unix функции Portable Open Server, обеспечивающей выполнение приложений Open Server в среде Open Unix и Open Linux.

Для обеспечения выполнения приложений Open Linux в среде Open Unix была разработана технология Linux Kernel Personality. Суть ее состоит в том, что в ядро Open Unix были включены специфические системные сервисы ядра Linux и таким образом обеспечено выполнение системных вызовов Linux. Процессы, составляющие "образ" той или иной ОС для пользователя, работают в пространстве пользователя. Системные вызовы обеих ОС выполняются одним ядром. Таким образом, достигается не эмуляция Linux на Unix, а действительная интеграция обеих ОС на уровне ядра.

Аналогичная технология Open Server Kernel Personality применена и для Open Server, причем процессы, выполняющиеся в разных операционных средах, могут взаимодействовать через обычные средства IPC. Специальный процесс File Update Daemon синхронизирует изменения файлов, сделанные в разных средах (три ОС используют разные файловые системы). Не вполне ясно, как ядро распознает системные вызовы от той или иной среды. Если в случае Linux Kernel Personality это должно быть достаточно просто: Unix использует для системных вызовов gateway, а Linux - int 80h, то Open Server также использует gateway, и отличить вызовы этой среды от вызовов Open Unix сложнее.

Таким образом, фирма Caldera является на сегодня ведущим производителем Unix-систем и деятельность фирмы позволяет сделать следующие выводы:

Контрольные вопросы

  1. Назовите известные вам коммерческие и некоммерческие клоны Unix.
  2. Что составляет системный и пользовательский контексты процесса?
  3. Как в современных версиях Unix поддерживаются процессы реального времени?
  4. Опишите две модели обеспечения нитей, применяемые в разных клонах Unix.
  5. Какие средства взаимодействия процессов в Unix вам известны?
  6. Какова логическая модель памяти в Unix? Как она реализуется в современных версиях этой ОС?
  7. Опишите работу процесса-сборщика страниц.
  8. Какие средства введены в Unix для обеспечения синхронизации нитей?
  9. Почему файловая система s5 не применяется в современных версиях Unix?
  10. Каковы общие свойства современных файловых систем Unix?
  11. В чем состоит целостность файловой системы, какими современными файловыми системами Unix и какими средствами она обеспечивается?
  12. Сопоставьте файловые системы vxfs или JFS и NTFS. Что между ними общего, в чем различия? <

НазадОглавлениеВперед
Индекс