\chapter{Файлы и файловые системы}
\label{filesystem}
\section{Что такое файл}
Вся информация на дисках компьютеров хранится в виде файлов. Что же
такое файл? По английски file означает картотечный ящик, и пошло, видимо
с тех пор, когда основным носителем информации были перфокарты (в
русском языке в те времена использовался термин <<колода перфокарт>>).


Впрочем, с тех пор смысл термина <<файл>> настолько измнился, что не
стоит пытаться найти ему адекватный перевод. Что же такое файл?
С точки зрения пользователя~--- некий кусок информации, который имеет
имя, и по этому имени на него можно ссылаться, например, указать
программе, что обрабатываемые данные нужно прочитать именно из этого
файла. Системы, ориентированные на неквалифицированного пользователя,
например MacOS, вместо термина <<файл>> используют термин <<документ>>,
что на мой взгляд приводит только к путанице. Далеко не каждый файл
является документом. С какой, например стати рассматривать как документ
программу? Ведь она предназначена не для чтения человеком, а для
выполнения компьютером. Хотя практически все, что можно сделать с файлом
вообще, можно сделать и с файлом программы~--- скопировать, переместить,
удалить, переслать по электронной почте.

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

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

Существует соглашение что формат файла обозначается суффиксом его имени
(этот суффикс часто называют <<расширением имени файла>>, англ
extension).
Например, если имя файла кончается на {\tt .jpg}, это картинка в формате
JPEG, а если на {\tt .tar} то это архив, который можно прочитать
программой {\tt tar}. \emph{Это не более чем соглашение.} Никто не
мешает его нарушить, хотя некоторые программы могут такого не понять.
Например, программа сжатия {\tt gzip} обычно отказывается распаковывать
файлы, если их имя не кончается на {\tt .gz} (её, конечно, несложно
заставить). Определить  настоящий формат файла, если этого нельзя
сделать по имени, поможет команда {\tt file}. Она считывает начало
файла, и ищет там определенные <<магические числа>>. Конечно, она не
всегда способна определить формат корректно. Например скрипты shell она
зачастую считает <<текстом на английском языке>> (что вообще-то не так
уж далеко от истины), а русский текст обычно не распознает и выдает
универсальное сообщение <<data>> (неопознанные данные).


Особенно активно связь расширения с форматом используется различными
визуальными средствами работы с файлами. Например, стандартная программа
<<Проводник>> в Windows по умолчанию вообще не показывает расширение
файла, заменяя его на иконку, соответствующую формату файла. И при
попытке открыть этот файл она вызовет именно ту программу, которая по её
мнению, предназначена для работы с файлами такого типа.

До предела этот подход доведен в MacOS где каждый файл имеет атрибут
creator (создавшая программа) и заставить систему обработать файл
какой-нибудь другой программой~--- задача нетривиальная.

Хотя такой подход немного уменьшает вероятность ошибок у начинающего
пользователя, он сильно снижает гибкость системы. Как мы уже обсуждали в
главе \ref{whatfor}, основное преимущество электронного хранения
информации~--- то, что к одним и тем же данным можно применить разные
программы. 

В Unix-подобных системах практически любой объект представляется в виде
файла. Даже терминал пользователя это специальный файл {\tt /dev/tty},
запись в который приводит к появлению символов на экране, а чтение
позволяет программе узнать, какие клавиши пользователь нажимает на
клавиатуре. Весь диск в целом тоже может рассматриваться как файл. В тех
случаях, когда нам неинтересна его внутренняя структура, например при
создании резервной копии.

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

\section{Файловые системы}

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

Поэтому файлы организованы в каталоги или директории (directiories). В
тех системах, где файл называют документом, обычно говорят о папках
(folders). Это достаточно хорошая метафора. Если представить себе, что
файл это бумажный лист, то несколько таких листов можно сложить в папку,
эту папку вместе с другими папками и листами~--- в папку побольше, и так
до тех пор пока мы не упихаем всю нашу информацию в большой шкаф.

Этот шкаф~--- корневой каталог файловой системы нашего компьютера,
содержащий в себе все, что лежит на его дисках. Сколько бы ни было у
компьютера физических дисков, в Unix (и в Windows 2000) пользователю они
все представляются как одно большое дерево каталогов. 

Операция присоединения диска к этому дереву называется монтированием.
Обычно пользователю не приходится заботиться о монтировании дисков~---
это привелигерованная операция, доступная только суперпользователю, и
обычно все необходимые диски, как локальные, так и удаленные (с других
компьютеров по сети) монтируются автоматически при старте системы. Но в
Linux системный администратор может предоставить пользователю право
монтировать дискеты и CD-ROM. 

В старых версиях Windows и в DOS операции
монтирования не было, там каждый диск получал свою собственную букву
(что ограничивало количество дисков 26) и имел свое собственное дерево
каталогов. Для дискет и CD-ROM это действительно удобно, но для жестких
дисков это только мешает эффективному распределению дискового
пространства. Кроме того, отсутствие явной операции
монтирования/размонтирования снижает эффективность работы с диском~---
каждая операция записи должна быть доведена до конца сразу, в то время
как при работе с монтированным диском система может отложить реальную
запись до того момента, когда это ей будет удобно (это называется
кэшированием).

Для CD-ROM это не так важно, поскольку записать на него ничего нельзя.
А вот вытаскивание дискеты без размонтирования может привести к порче
информации на ней. Поэтому лично я предпочитаю не монтировать дискеты
вообще, а пользоваться для доступа к ним программой {\tt mtools}.

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

Более того, в Unix нет операции уничтожения \emph{файла}, есть операция
уничтожения ссылки в каталоге. И как в любой бюрократической системе,
файл, на который не осталось ни одной ссылки, исчезает бесследно
(освобождая ранее занятое место). На самом деле ссылкой на файл
считается не только запись в каталоге, но и факт работы с файлом
какой-нибудь программы. Поэтому если вы удалили файл, который читает или
пишет какая-то программа, место на диске не освободится, пока эта
программа файл не закроет.

Кроме собственно данных с файлом связана некоторая метаинформация~---
имя пользователя-владельца, размер файла, права доступа, время
последнего изменения и так далее. Эта информация хранится в так
называемом индексном узле (i-node) вместе с информацией о том, где
физически размещены данные. А запись в каталоге состоит из имени
и номера индексного узла. Поэтому разные ссылки на один и тот же файл
могут иметь разные имена.

\section{Права доступа к файлам}

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

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

Особый смысл имеет привилегия выполнения для каталога~--- это право на
вход в него, необходимое для доступа к любому файлу в этом каталоге или
каком-либо из его подкаталогов.

Традиционно в Unix различаются три категории пользователей~--- владелец
файла, группа и все остальные\footnote{Не забывайте, что есть еще и
root, который может читать и писать в любые файлы в системе, независимо
от установленных прав доступа}. В принципе этого достаточно для описания
достаточно сложных способов доступа, поскольку можно создать сколько
угодно групп. В современных дистрибуитвах Linux по умолчанию для каждого
пользователя создается его собственая группа, куда входит только он, и
все вновь создаваемые файлы создаются с правом чтения и записи для
владельца и для группы, и только чтения для остальных.

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

Вновь создаваемый файл получает либо основную группу своего владельца,
либо группу каталога, в котором создан этот файл. Владелец файла имеет
право изменить группу файла с помощью команды {\tt chgrp}, но только на 
такую, членом которой он
является (узнать список групп, в которые вы входите можно с помощью
команды {\tt id}). Исходно в Unix была возможность <<подарить>> файл
другому пользователю, с помощью команды {\tt chown} но выяснилось, что
это открывает слишком много возможностей для злоупотреблений, например
если вам не хватает выделенной вам квоты дискового пространства, вы
могли назначить нескольким самым большим файлам владельцем кого-нибудь
другого. Были и другие, более опасные способы атаки, которые позволяли
получить права root, путем хитроумного использования команды {\tt
chown}. Поэтому в совремемнных Unix пользоваться командой chown имеет
право только root.

