Функционирование системы UNIX

Выполнение процессов

Процесс может выполняться в одном из двух состояний, а именно пользователь­ском и системном. В пользовательском состоянии процесс выполняет пользо­вательскую программу и имеет доступ к пользовательскому сегменту данных. В системном состоянии процесс выполняет программы ядра и имеет доступ к системному сегменту данных.

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

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

Подсистема ввода/вывода

Функции ввода/вывода в UNIX задаются в основном с помощью пяти систем­ных вызовов, а именно: open, close, read, write и seek.

Те же самые команды ввода/вывода применяются и к физическим устройствам. В системе UNIX физические устройства представлены специальными файлами в единой структуре файловой системы. Это означает, что пользователь не может написать зависящую от устройств программу, если только эта зависимость не от­ражена в самом потоке передаваемых данных. Стандартные файлы ввода и выво­да, приписываемые пользовательскому терминалу, открывать обычным путем не требуется. Терминал открывается автоматически по команде входа в систему – login.

Система ввода/вывода UNIX, в отличие от большинства других систем, ориенти­рована скорее на работу с потоком, а не с записями. Здесь поток (stream) – это последовательность байтов, заканчивающаяся разделителем (то есть символом конца потока end-of-stream). Понятие потока позволяет проще добиться неза­висимости от устройств и унификации файлов с физическими устройствами и транспортерами (конвейерами). Тем самым пользователь получает гибкость в работе с группами данных, но на него ложатся и дополнительные заботы, по­скольку ему приходится писать программы управления данными. Пользователь может при необходимости относительно легко самостоятельно реализовать ра­боту с записями. Чтобы работать с записями фиксированной длины, достаточно просто задавать постоянную длину во всех командах чтения и записи. Прямой доступ при фиксированной длине записей получается путем умножения длины записи на номер записи и выполнения команды seek для нахождения позиций нужной записи. Работу с записями переменной длины можно организовать, если разместить в начале каждой записи поле фиксированного размера, содержащее длину записи.

Перенаправление ввода/вывода

Механизм перенаправления ввода/вывода является одним из наиболее элегант­ных, мощных и одновременно простых механизмов ОС UNIX. Цель, которая ставилась при разработке этого механизма, состоит в следующем. Поскольку UNIX это интерактивная система, которая создавалась в конце 60-х – начале 70-х годов, то обычно программы вводили текстовые строки с терминала и выво­дили результирующие текстовые строки на экран терминала. Для того чтобы обеспечить более гибкое использование таких программ, желательно было уметь обеспечить им ввод из файла или из вывода других программ и направить их вы­вод в файл или на ввод другим программам.

Реализация этого механизма основывается на следующих свойствах ОС UNIX. Во-первых, любой ввод/вывод трактуется как ввод из некоторого файла и вывод в некоторый файл. Клавиатура и экран терминала тоже интерпретируются как файлы (первый можно только читать, а во второй можно только писать). Во-вто­рых, доступ к любому файлу производится через его дескриптор (положитель­ное целое число). Фиксируются три значения дескрипторов файлов. Файл с дескриптором 1 называется файлом стандартного ввода (std1n), файл с дескрип­тором 2 – файлом стандартного вывода (stdout) и файл с дескриптором 3 – файлом стандартного вывода диагностических сообщений (stderr). В-третьих, программа, запущенная в некотором процессе, «наследует» от породившего про­цесса все дескрипторы открытых файлов.

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

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

Структура файловой системы

Файл в системе UNIX представляет собой множество символов с произвольным доступом. В файле содержатся произвольные данные, помещенные туда пользо­вателем, и файл не имеет никакой другой структуры, кроме той, какую налагает на него пользователь.

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

Информация на дисках размещается поблочно, по 512 байт в каждом блоке. Диск разбивается на следующие области (рис. 5.2):

неиспользуемый блок;

управляющий блок или суперблок, в котором содержится размер диска и гра­ницы других областей;

i-список, состоящий из описаний файлов, называемых i-узлами;

область для хранения содержимого файлов.

Каждый i-узел содержит:

идентификацию владельца;

идентификацию группы владельца;

биты защиты;

физические адреса на диске или ленте, где находится содержимое файла;

размер файла;

время создания файла;

время последнего использования файла (modification time);

время последнего изменения атрибутов (change time);

число связей-ссылок, указывающих на файл;

индикацию, является ли файл директорией, обычным файлом или специаль­ным файлом.

Следом за i-списком идут блоки, предназначенные для хранения содержимого файлов. Пространство на диске, оставшееся свободным от файлов, образует свя­занный список свободных блоков.

Таким образом, файловая система UNIX представляет собой структуру данных, размещенную на диске и содержащую управляющий суперблок, в котором опре­делена файловая система в целом; массив i‑узлов, где определены все файлы в файловой системе; сами файлы; и, наконец, совокупность свободных блоков. Выделение пространства под данные осуществляется блоками фиксированного размера.

Каждый файл однозначно идентифицируется старшим номером устройства, младшим номером устройства и i-номером (индексом i‑узла данного файла в массиве i-узлов). Когда вызывается драйвер устройства, по старшему номеру ин­дексируется массив входных точек в драйверы. По младшему номеру драйвер выбирает одно устройство из группы идентичных физических устройств.

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

Большое число системных директорий система UNIX использует для своих соб­ственных нужд. Одна из них, корневая директория, является базой для всей структуры директорий, и, «отталкиваясь» от нее, можно найти размещение всех файлов. В других системных директориях содержатся программы и команды, предоставляемые пользователям, и файлы устройств.

Имена файлов задаются последовательностью имен директорий, разделенных косой чертой («/») и приводящих к концевому узлу (листу) некоторого дерева.

Файл, не являющийся директорией, может встречаться в различных директориях, возможно, под разными именами. Это называется связыванием. Элемент в ди­ректории, относящийся к одному файлу, называется связью. В системе UNIX все такие связи имеют равный статус. Файлы не принадлежат директориям. Скорее, файлы существуют независимо от элементов директорий, а связи в директориях указывают действительно на физические файлы. Файл «исчезает», когда удаля­ется последняя связь, указывающая на него. Биты защиты, заданные в связях, могут отличаться от битов в исходном файле. Таким образом, решается пробле­ма избирательного ограничения доступа к файлам.

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

От файловой системы не требуется, чтобы она вся целиком размещалась на том устройстве, где находится корень. Запрос от системы mount (на установку носите­лей и т. п.) позволяет встраивать в иерархию файлов файлы на сменных томах. В результате выполнения команды mount файловая система, расположенная на указанном устройстве, подключается к системе таким образом, что ее содер­жимое заменяет собой содержимое заданного в команде каталога. Ко­манда umount выполняет обратную операцию – «отсоединяет» (размонтирует) файловую систему, после чего диск с данными можно физически извлечь из сис­темы. Например, для записи данных на дискету необходимо ее смонтировать, а после работы – размонтировать.

Защита файлов

Защита файлов осуществляется при помощи номера, идентифицирующего поль­зователя, и установки десяти битов защиты – атрибутов доступа. Права доступа подразделяются на три типа: чтение (read), запись (write) и выполнение (execute). Эти типы прав доступа могут быть предоставлены трем классам пользователей: владельцу файла, группе, в которую входит владелец, и всем (прочим) пользова­телям. Файл всег­да связан с определенным пользовате­лем – своим владельцем – и с определенной группой, то есть у него есть уже UID (user ID, идентификатор пользователя) и GID (group ID, идентификатор группы). Изменять права доступа к файлу разрешено только его владельцу. Изменить владельца файла может суперпользователь, группу – су­перпользователь или владелец файла.

Программа, выполняющаяся в системе, всегда запускается от имени какого-то пользователя и какой-то группы (обычно – основной группы этого пользова­теля), но связь процессов с пользователями и группами организована сложнее: здесь различаются идентификатор для доступа к файловой системе (FSUID – file system access user ID, FSGID – file system access group ID) и эффективный идентификатор (EUID – effective user ID, EGID – effective group ID), а при доступе к файлам учитываются еще и полномочия (capabilities), присвоенные само­му процессу.

При создании файл получает UID, совпадающий с FSUID процесса, который его создает, и, как правило, GID, совпадающий с FSGID этого процесса.

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

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

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

Помимо трех названных основных атрибутов доступа существуют дополнитель­ные, используемые в следующих случаях. Атрибуты SUID и SGID существенны при запуске программы на выполнение; они требуют, чтобы программа выполня­лась не от имени запустившего ее пользователя (группы), а от имени владель­ца (группы) того файла, в котором она находится. Выражаясь формально, если файл программы имеет атрибут SUID (SGID), то FSUID и EUID (FSGID и EGID) соответствующего процесса не наследуются от процесса, запустившего его, а сов­падают с UID (GID) файла. Благодаря этому пользователи получают возмож­ность запустить системную программу, которая создает свои рабочие файлы в закрытых для них каталогах.

Кроме того, если процесс создает файл в каталоге, имеющем атрибут SGID, то файл получает GID не по FSGID процесса, а по GID каталога. Это удобно для коллективной работы: все файлы и подкаталоги в каталоге автоматически ока­зываются принадлежащими одной и той же группе, хотя создавать их могут раз­ные пользователи. Есть еще один атрибут – CVTX, который теперь относится к каталогам. Он показывает, что из каталога, имеющего этот атрибут, ссылку на файл может удалить только владелец файла.

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

«-» – обычный файл;

«d» – каталог (директория);

«с» – символьное устройство;

«b» – блочное устройство;

«р» – именованный канал (named pipe);

«s» – «гнездо» (socket);

«I» – символическая ссылка.

Далее следуют три последовательности, каждая из трех символов, соответствую­щие правам пользователя, группы и всех остальных. Наличие права на чтение обозначается буквой «r», на запись – «w», на выполнение – «х», отсутствие ка­кого-либо права – знаком «-» в соответствующей позиции.

Наличие атрибута SUID (SGID) обозначается заглавной буквой «S» в позиции права на выполнение для владельца (группы), если выполнение не разрешено, и прописной буквой «s», если разрешено.

Восьмеричная запись – это шестизначное число, первые два знака которого обозначают тип файла и довольно часто опускаются, третья цифра – атрибуты GUID (4), SGID (2) и SVTX (1), а оставшиеся три – соответственно права вла­дельца, группы и всех остальных. Очевидно, что право на чтение можно предста­вить числом «4», право на запись – числом «2», а право на выполнение кодиру­ется как «1». Например, стандартный набор прав доступа для каталога /tmp в символьной фор­ме выглядит как drwxrwxrwt, а в восьмеричной – как 041777 (это каталог; чтение, запись и поиск разрешены всем; установлен атрибут SVTX). А набор прав -r-S-xw-, или в числовом виде – 102412, будет означать, что это обычный файл, владельцу разрешается читать его, но не выполнять и не изменять; пользователям из груп­пы файла (за исключением владельца) – выполнять (причем во время работы программа получит права владельца файла), но не читать и не изменять; а всем остальным – изменять, но не читать и не выполнять.

Наши рекомендации