Перенаправление ввода-вывода
Механизм перенаправления ввода-вывода является одним из наиболее элегантных, мощных и одновременно простых механизмов UNIX. Цель, которая ставилась при разработке этого механизма, состоит в следующем. Поскольку UNIX — это интерактивная система, которая создавалась в конце 60-х — начале 70-х годов, то обычно программы считывали текстовые строки с алфавитно-цифрового терминала и выводили результирующие текстовые строки на экран терминала. Для того чтобы обеспечить большую гибкость при использовании таких программ, желательно было иметь возможность вводить в них данные непосредственно из файлов или с выхода других программ и выводить их данные в файл или на вход других программ.
Реализация этого механизма основывается на следующих свойствах операционных систем семейства UNIX. Во-первых, любой ввод-вывод трактуется как ввод из некоторого файла и вывод в некоторый файл. Клавиатура и экран терминала тоже интерпретируются как файлы (первый можно только читать, а во второй можно только писать). Во-вторых, доступ к любому файлу производится через его дескриптор (положительное целое число). Фиксируются три значения дескрипторов файлов. Файл с дескриптором 1 называется файлом стандартного ввода (stdin), файл с дескриптором 2 — файлом стандартного вывода (stdout), и файл с дескриптором 3 — файлом стандартного вывода диагностических сообщений (stderr). В-третьих, программа, запущенная в некотором процессе, «наследует» от породившего процесса все дескрипторы открытых файлов.
1 Не путать с потоком выполнения, или тредом (thread).
Семейство операционных систем UNIX____________________________________ 323
В головном процессе интерпретатора командного языка файлом стандартного ввода является клавиатура терминала пользователя, а файлами стандартного вывода и вывода диагностических сообщений — экран терминала. Однако при запуске любой команды можно сообщить интерпретатору (средствами соответствующего командного языка), какой файл или выход какой программы должен служить файлом стандартного ввода для запускаемой программы, а также какой файл или вход какой программы должен служить для запускаемой программы файлом стандартного вывода или файлом вывода диагностических сообщений. Тогда интерпретатор перед выполнением системного вызова exec открывает указанные файлы, подменяя смысл дескрипторов 1, 2 и 3.
То же самое может проделать и любая другая программа, запускающая третью программу в специально созданном процессе. Следовательно, все, что требуется для нормального функционирования механизма перенаправления ввода-вывода, — это придерживаться при программировании соглашения об использовании дескрипторов stdin, stdout и stderr. Это не очень трудно, поскольку в наиболее распространенных функциях библиотеки ввода-вывода printf, scanf и error вообще не требуется указывать дескриптор файла. Функция printf неявно использует дескриптор stdout, функция scanf — дескриптор stdin, функция error— дескриптор stderr.
Файловая система
Файл в системе UNIX представляет собой множество символов с произвольным доступом. В файле могут содержаться любые данные, помещенные туда пользователем, и файл не имеет никакой иной структуры, кроме той, какую создаст в нем пользователь.
Структура файловой системы
Здесь мы вкратце рассмотрим одну из первых реализаций файловой системы, поскольку основные ее идеи сохраняются до сих пор.
Информация на дисках размещается блоками. В первой версии файловой системы размер блока был равен 512 байт. Во многих современных файловых системах, разработанных для конкретной версии UNIX-клона, размер блока больше. Это позволяет повысить быстродействие файловых операций. Например, в системе FFS (Fast File System — быстродействующая файловая система) размер блока равен 8192 байт.
В рассматриваемой версии файловой системы раздел диска разбивается на следующие области (рис. 10.1):
- неиспользуемый блок;
- управляющий блок, или суперблок, в котором хранится размер логического диска и границы других областей;
- z'-список, состоящий из описаний файлов, называемых /-узлами;
- область для хранения содержимого файлов.
324________________ Глава 10. Краткий обзор современных операционных систем
Рис. 10.1. Организация файловой системы в ОС UNIX
Каждый г-узел содержит:
- идентификатор владельца;
- идентификатор группы владельца;
- биты защиты;
- физические адреса на диске или ленте, где находится содержимое файла;
- размер файла;
- время создания файла;
- время последнего изменения (modification time) файла;
Семейство операционных систем UNIX____________________________________ 325
- время последнего изменения атрибутов (change time) файла;
- число связей-ссылок, указывающих на файл;
- индикатор типа файла (каталог, обычный файл или специальный файл).
Следом за г-списком идут блоки, предназначенные для хранения содержимого файлов. Пространство на диске, оставшееся свободным от файлов, образует связанный список свободных блоков.
Таким образом, файловая система UNIX представляет собой структуру данных, размещенную на диске и содержащую управляющий суперблок с описанием файловой системы в целом, массив г-узлов, в котором определены все файлы в файловой системе, сами файлы и, наконец, совокупность свободных блоков. Выделение пространства под данные осуществляется блоками фиксированного размера.
Каждый файл однозначно идентифицируется старшим номером устройства, младшим номером устройства и i-номером (индексом /-узла данного файла в массиве г-узлов). Когда вызывается драйвер устройства, по старшему номеру индексируется массив входных точек в драйверы. По младшему номеру драйвер выбирает одно устройство из группы идентичных физических устройств.
Файл-каталог, в котором перечислены имена файлов, позволяет установить соответствие между именами и самими файлами. Каталоги образуют древовидную структуру. На каждый обычный файл или файл устройства могут иметься ссылки в различных узлах этой структуры. В непривилегированных программах запись в каталог не разрешена, но при наличии соответствующих разрешений они могут читать их. Дополнительных связей между каталогами нет.
Большое число системных каталогов UNIX использует для собственных нужд. Один из них, корневой каталог, является базой для всей структуры каталогов, и, «отталкиваясь» от него, можно найти все файлы. В других системных каталогах содержатся программы и команды, предоставляемые пользователям, а также файлы устройств.
Имена файлов задаются последовательностью имен каталогов, разделенных косой чертой (/) и приводящих к концевому узлу (листу) некоторого дерева. Если имя файла начинается с косой черты, то поиск по дереву начинается в корневом каталоге. Если же имя файла не имеет в начале косой черты, то поиск начинается с текущего каталога. Имена файлов, начинающиеся с символов ../ (две точки и косая черта), подразумевают начало поиска в каталоге, родительском по отношению к текущему. Имя файла stuff (персонал) указывает на элемент stuff в текущем каталоге. Имя файла /work/alex/stuff приводит к поиску каталога work в корневом каталоге, затем к поиску каталога alex в каталоге work и, наконец, к поиску элемента stuff в каталоге alex. Сама по себе косая черта (/) обозначает корневой каталог. В приведенном примере нашла отражение типичная иерархическая структура файловой системы, например work может обозначать диск (устанавливаемый при работе пользователя), alex может быть каталогом пользователя, a stuff может принадлежать alex.
Файл, не являющийся каталогом, может встречаться в различных каталогах, возможно, под разными именами. Это называется связыванием. Элемент в каталоге,
326________________ Глава 10. Краткий обзор современных операционных систем
относящийся к одному файлу, называется связью. В UNIX-системах все такие связи имеют равный статус. Файлы не принадлежат каталогам. Скорее, файлы существуют независимо от элементов каталогов, а связи в каталогах указывают на реальные (физические) файлы. Файл «исчезает», когда удаляется последняя связь, указывающая на него. Биты защиты, заданные в связях, могут отличаться от битов в исходном файле. Таким образом решается проблема избирательного ограничения на доступ к файлам.
С каждым поддерживаемым системой устройством ассоциируется один или большее число специальных файлов. Операции ввода-вывода для специальных файлов осуществляются так же, как и для обычных дисковых файлов с той лишь разницей, что эти операции активизируют соответствующие устройства. Специальные файлы обычно находятся в каталоге /dev. На специальные файлы могут указывать связи точно так же, как на обычные файлы.
От файловой системы не требуется, чтобы она целиком размещалась на том устройстве, где находится корень. Запрос от системы mount (на установку носителей и т. п.) позволяет встраивать в иерархию файлов файлы на сменных томах. Команда mount имеет несколько аргументов, но обязательных аргументов у стандартного варианта ее использования два: имя файла блочного устройства и имя каталога. В результате выполнения этой команды файловая подсистема, расположенная на указанном устройстве, подключается к системе таким образом, что ее содержимое заменяет собой содержимое заданного в команде каталога. Поэтому для монтирования соответствующего тома обычно используют пустой каталог. Команда umount выполняет обратную операцию — «отсоединяет» файловую систему, после чего диск с данными можно физически извлечь из системы. Например, для записи данных на дискету необходимо ее «подмонтировать», а после работы — «размонтировать».
Монтирование файловых систем позволяет получить единое логическое файловое пространство, в то время как реально отдельные каталоги с файлами могут находиться в разных разделах одного жесткого диска и даже на разных жестких дисках. Причем, что очень важно, сами файловые системы для монтируемых разделов могут быть разными. Например, при работе в системе Linux мы можем иметь часть разделов с файловой системой EXT2FS, а часть разделов — с файловой системой EXT3FS. Важно, чтобы ядро знало эти файловые системы.
Защита файлов
Защита файлов осуществляется при помощи номера, идентифицирующего пользователя, и десяти битов защиты — атрибутов доступа. Права доступа подразделяются на три типа: чтение (read), запись (write) и выполнение (execute). Эти типы прав доступа могут быть предоставлены трем классам пользователей: владельцу файла, группе, в которую входит владелец, и всем прочим пользователям. Девять из этих битов управляют защитой по чтению, записи и исполнению для владельца файла, других членов группы, в которую входит владелец, и всех других пользователей. Файл всегда связан с определенным пользователем — своим владельцем и с определенной группой, то есть у него есть уже известные нам идентификаторы
Семейство операционных систем UNIX___________________________________ 327
пользователя (UID) и группы (GID). Изменять права доступа к файлу разрешено только его владельцу. Изменить владельца файла может только суперпользователь, изменить группу — суперпользователь или владелец файла.
Программа, выполняющаяся в системе, всегда запускается от имени определенных пользователя и группы (обычно основной группы этого пользователя), но связь процессов с пользователями и группами организована сложнее. Различают идентификаторы доступа к файловой системе для пользователя (File System access User ID, FSUID) и для группы (File System access Group ID, FSGID), а также эффективные идентификаторы пользователя (Effective User ID, EUID) и группы (Effective Group ID, EGID). Кроме того, при доступе к файлам учитываются полномочия (capabilities), присвоенные самому процессу.
При создании файл получает идентификатор UID, совпадающий с FSUID процесса, который его создает, а также идентификатор GID, совпадающий с FSGID этого процесса.
Атрибуты доступа определяют, что разрешено делать с данным файлом данной категории пользователей. Имеется всего три операции: чтение, запись и выполнение.
При создании файла (или при создании еще одного имени для уже существующего файла) модифицируется не сам файл, а каталог, в котором появляются новые ссылки на узлы. Удаление файла заключается в удалении ссылки. Таким образом, право на создание или удаление файла — это право на запись в каталог.
Право на выполнение каталога интерпретируется как право на поиск в нем (прохождение через него). Оно позволяет обратиться к файлу с помощью пути, содержащему данный каталог, даже тогда, когда каталог не разрешено читать, и поэтому список всех его файлов недоступен.
Помимо трех названных основных атрибутов доступа существуют дополнительные, используемые в следующих случаях. Атрибуты SUID и SGID важны при запуске программы: они требуют, чтобы программа выполнялась не от имени запустившего ее пользователя (группы), а от имени владельца (группы) того файла, в котором она находится. Если файл программы имеет атрибут SUID (SGID), то идентификаторы FSUID и EUID (FSGID и EGID) соответствующего процесса не наследуются от процесса, запустившего его, а совпадают с UID (GID) файла. Благодаря этому пользователи получают возможность запустить системную программу, которая создает свои рабочие файлы в закрытых для них каталогах.
Кроме того, если процесс создает файл в каталоге, имеющем атрибут SGID, то файл получает GID не по идентификатору FSGID процесса, а по идентификатору GID каталога. Это удобно для коллективной работы: все файлы и вложенные каталоги' в каталоге автоматически оказываются принадлежащими одной и той же группе, хотя создавать их могут разные пользователи. Есть еще один атрибут SVTX, который нынче относится к каталогам. Он показывает, что из каталога, имеющего этот атрибут, ссылку на файл может удалить только владелец файла. Существуют две стандартные формы записи прав доступа — символьная и восьмеричная. Символь-
' Вложенные каталоги часто называют подкаталогами (subdirectory).
328________________ Глава 10. Краткий обзор современных операционных систем
ная запись представляет собой цепочку из десяти знаков, первый из которых не относится собственно к правам, а обозначает тип файла. Используются следующие обозначения:
- - (дефис) — обычный файл;
- d - каталог;
- с - символьное устройство;
- b - блочное устройство;
- р - именованный канал (named pipe);
- s - со кет (socket)1;
- I - символическая ссылка.
Далее следуют три последовательности, каждая из трех символов, соответствующие правам пользователя, группы и всех остальных. Наличие права на чтение обозначается символом г, на запись — символом w, на выполнение — символом х, отсутствие какого-либо права — символом - (дефис) в соответствующей позиции.
Наличие атрибута SUID (SGID) обозначается прописной буквой S в позиции права на выполнение для владельца (группы), если выполнение не разрешено, и строчной буквой s, если разрешено.
Восьмеричная запись — это шестизначное число, первые два знака которого обозначают тип файла и довольно часто опускаются, третья цифра — атрибуты GUID (4), SGID (2) и SVTX (1), оставшиеся три — права владельца, группы и всех остальных соответственно. Очевидно, что право на чтение можно представить числом 4, право на запись — числом 2, а право на выполнение — числом 1.
Например, стандартный набор прав доступа для каталога /tmp в символьной форме выглядит как drwxrwxrwx, а в восьмеричной — как 041777 (каталог; чтение, запись и поиск разрешены всем; установлен атрибут SVTX). А набор прав -r-S-xw-, или в числовом виде — 102412, означает, что это обычный файл, владельцу разрешается читать его, но не выполнять и не изменять, пользователям из группы (за исключением владельца) — выполнять (причем во время работы программа получит права владельца файла), но не читать и не изменять, а всем остальным — изменять, но не читать и не выполнять.
Большинство программ создают файлы с разрешением на чтение и запись для всех пользователей, а каталоги — с разрешением на чтение, запись и поиск для всех пользователей. Этот исходный набор атрибутов логически складывается с пользовательской маской создания файла (user file-creation mask, umask), которая обычно ограничивает доступ. Например, значения u=rwx, g=rwx, o=r-x для пользовательской маски следует понимать так: у владельца и группы остается полный набор прав, а всем остальным запрещается запись. В восьмеричном виде оно запишется как 002 (первая цифра — ограничения для владельца, вторая — для группы, третья — для
1 Сокет — это понятие, связанное со стеком протоколов TCP/IP, который является «родным» для UNIX. Его следует понимать как некий адрес или порт, через который связываются удаленные программы.
Семейство операционных систем UNIX____________________________________ 329
остальных; запрещение чтения — 4, записи — 2, выполнения — 1). Владелец файла может изменить права доступа к нему командой chmod.