10. Как мой компьютер хранит информацию на диске?

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

10.1. Низкоуровневая структура диска и файловой системы

Поверхность вашего диска, на которой хранятся данные, разделена примерно как мишень для метания дротиков — круговые дорожки разрезанные секторами. Вследствие того что дорожки близкие к внешнему краю имеют бОльшую длину, чем те что ближе к шпинделю в центре диска, внешние дорожки имеют больше секторов, чем внутренние. Все сектора (или блоки диска (disk block)) имеют одинаковый размер, в современных Unix это обычно 1 двоичная тысяча (1024 8-битовых слов). Каждый блок диска имеет уникальный адресс или номер блока диска (disk block number).

Unix разбивает диск на разделы (disk partitions). Каждый раздел это непрерывный интервал блоков, используемый отдельно от любого другого раздела, например файловая система и область подкачки (swap space). Изначально причины, по которым возникла необходимость создавать на диске разделы это восстановление после сбоев медленных и склонных к возникновению ошибок дисков; границы между разделами уменьшают вероятность возникновения ситуации когда в результате возникновения произвольной ошибки на диске вы целиком теряете к нему доступ. В наши дни более важным является то, что раздел можно объявить доступными только для чтения (read-only) (воизбежание модификации злоумышленником критично важных системных файлов) или сделать доступным (с разными целями, которые мы здесь не обсуждаем) по сети. Раздел с наименьшим номером (загрузочный раздел (boot partition)) создается специально для размещения на нем загружаемого ядра.

Раздел мождет быть либо областью подкачки (swap space) (используемой для работы виртуальной памяти (virtual memory)) или файловой системой (file system), используемой для хранения файлов. Раздел области подкачки трактуется системой просто как линейная последовательность блоков. Файловые системы, напротив, нуждаются в схеме расположения последовательности блоков файлов. Потому что, файлы время от времени изменяются, растут и уменьшаются, поэтому блоки данных файла могут не располагаться последовательно, а разбросаны по всему разделу (куда бы ни положила их операционная система когда нуждалась в свободном блоке). Этот эффект разрозненности называется фрагментацией (fragmentation).

10.2. Имена файлов и каталогов

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

Каждый i-node содержит список номеров блоков диска файла, который он описывает. (В действительности это соответствует истине только на половину, это верно только для небольших файлов, но остальные подробности здесь не важны). Стоит отметить, что i-node не содержит имени файла.

Имена файлов живут в структурах называемых каталоги (directory structures). Каталог это структура, представляющая из себя простую таблицу имен файлов и соответствующие им номера i-node. Вот почему в Unix файл может иметь несколько настоящих имен (или жестких ссылок (hard links)); просто в католог вносятся записи указывающие на один и тот же i-node.

10.3. Точки монтирования

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

Непосредственно в начале загрузки системы вы можете получить доступ только к вашему корневому разделу (root partition), который является (почти всегда) загрузочным. Он содержит корневой каталог файловой системы и является исходной точкой дерева каталогов.

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

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

10.4. Как система узнает где лежит файл

Теперь мы можем взглянуть на файловую систему сверху вниз. Когда вы открываете файл (скажем, такой как, /home/esr/WWW/ldp/fundamentals.xml) вот что происходит:

Ваша ядро начинает обзор с корневого каталога файловой системы вашей Unix (корневого раздела). Она ищет каталог с именем ‘home’. Обычно ‘home’ это точка монтирования большого пользовательского раздела, тогда оно идет туда. На верхнем уровне структуры каталога этого пользовательского раздела, оно ищет запись с именем ‘esr’ и извлекает номер i-node. Идет к этому i-node, отметим, что в блоках данных ассоциированных с этим файлом находится структура каталога, ищет ‘WWW’. Извлекает его i-node, и идет дальше к соответствующему подкаталогу и ищет в нем ‘ldp’. Это дает еще один i-node каталога. Открывая его, находит номер i-node для ‘fundamentals.xml’. Этот i-node не каталог, но содержит список блоков диска ассоциированных с этим файлом.

10.5. Владелецы файлов, права доступа и безопасность

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

Для понимания системы прав доступа, вам надо вернуться к описанию понятий пользователей и групп в разделе Что происходит когда вы входите в систему (log in)?.Каждый файл имеет владеющего им пользователя и группу. Изначально владельцем является создатель файла; затем он может быть изменен с помощью программ chown(1) и chgrp(1).

Основные права , которые могут быть ассоциированы с файлом это ‘чтение’ (‘read’) (право чтения данных из файла), ‘запись’ (‘write’) (право изменять его) и ‘выполнение’ (‘execute’) (право запускать его как программу). Каждый файл имеет три набора прав; один для его пользователя-владельца, другой для любого пользователя входящего в группу владельцев, и один для всех остальных пользователей. ‘Привилегии’, которые вы получаете когда входите в систему, это просто способность читать, изменять и выполнять файлы, имеющие установленные биты прав соответствующие вашему идентификатору пользователя (user ID) или одной из групп, в которую вы включены; а также файлы доступные в системе всем.

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


snark:~$ ls -l notes
-rw-r--r--   1 esr      users         2993 Jun 17 11:00 notes

Это обычный файл данных. Вывод списка говорит нам, что файл принадлежит пользователю ‘esr’ и группе пользователей ‘users’. Возможно, машина на которой мы работаем, включает всех обычных пользователей в эту группу по умолчанию; другие группы, которые вы можете обычно встретить на машинах с разделением времени это ‘staff’, ‘admin’, или ‘wheel’ (по понятным причинам, группы не так важны на однопользовательских рабочих станциях и ПК). В вашей Unix по умолчанию может использоваться другая группа, возможно ее имя совпадает с именем вашего пользовательского идентификатора.

В строке ‘-rw-r--r--’ представлены биты прав для этого файла. Самая первая позиция предназначена для обозначения каталогов и символьных ссылок, сейчас там прочерк, если бы этот файл был каталогом, то там было бы указано ‘d’, и ‘l’ для символьной ссылки. Следующие три позиции отображают права доступа пользователя, затем три позиции это права доступа группы, и последние три показывают какие права доступа имеют все остальные пользователи (часто называемые ‘миром’ (‘world’). Владелец этого файла, пользователь ‘esr’ может и читать и изменять его, другие люди входящие в группу ‘users’ могут только читать, все другие также имеют право только читать файл. Это довольно типичный набор прав доступа для обыкновенного файла данных.

Сейчас давайте посмотрим на файл с другими правами доступа. Этот файл GCC, компилятор GNU с языка C.


snark:~$ ls -l /usr/bin/gcc
-rwxr-xr-x   3 root     bin         64796 Mar 21 16:41 /usr/bin/gcc

Этот файл принадлежит пользователю с именем ‘root’ и группе названной ‘bin’; он может быть перезаписан (изменен) только пользователем root, но прочитан и запущен на выполнение любым. Это обычные настройки владельцев файла и набор прав доступа для предустановленных системных программ. Группа ‘bin’ существует на некоторых Unix для того чтобы собрать вместе системные команды (ее имя это исторический пережиток, сокращение от ‘binary’). В вашей системе вместо нее может использоваться группа ‘root’ (совсем не тоже самое, что пользователь ‘root’!).

Имя пользователя ‘root’ это условное обозначение пользователя с номером идентификатора 0 (ID 0), это специальная привилигерованная учетная запись пользователя, который может делать в системе все не взирая ни на что. Доступ к системе под root значителен, но небезопасен; при работе в системе под root, даже опечатка в команде может полностью повредить или уничтожить критично важные системные файлы, в то время как эта же команда выполненная под учетной записью обычного пользователя не сможет этого сделать.

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

О паролях: не записывайте их и не используйте пароли, которые могут быть легко подобраны, такие как имя вашей девушки/парня/супруга. Эта удивительно, но именно подобная плохая практика, без конца помогает взломщикам. Подходя более универсально, не выбирайте вообще какое-либо слово из словаря; существуют программы называемые взломщик со справочником (dictionary crackers), подбирающие пароли из списка частоиспользуемых слов. Хороший прием выбора пароля, это взять комбинацию слова и цифры и другого слова, например, ‘shark6cider’ или ‘jump3joy’; это сделает пространство поиска слишком большим для взломщика со словарем. не используйте эти примеры — после прочтения этого документа взломщики могут добавить их в свои словари.

Теперь рассмотрим третий случай:


snark:~$ ls -ld ~
drwxr-xr-x  89 esr      users          9216 Jun 27 11:29 /home2/esr
snark:~$ 

Этот файл является каталогом (на это указывает ‘d’ в первой позиции). Мы видим, что изменен он может быть только пользователем esr, но читать и выполнять могут все.

Право чтения дает возможность просматривать каталог — видеть имена файлов и каталогов, которые он сожержит. Право изменять каталог дает возможность создавать и удалять в нем файлы. Если вы вспомните, что каталог это файл со списком содержащихся в нем файлов и подкаталогов, то это правило станет понятным.

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

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

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

В заключение, давайте посмотрим на права доступа программы login.


snark:~$ ls -l /bin/login
-rwsr-xr-x   1 root     bin         20164 Apr 17 12:57 /bin/login

Как мы и ожидали, наблюдаем набор прав доступа как у системной команды, за исключением ‘s’, где должен был находится бит права выполнения для владельца. Это видимое проявление специального права называемого установка прав пользователя ‘set-user-id’ или setuid it.

Бит setuid обычно добавляется к программам нуждающимся в том, чтобы дать права root обычному пользователю, но конроллируемым способом. Когда он устанавливается на выполняемую программу, вы получаете привилегии владельца этой программы на время ее выполнения от вашего имени, в любом случае, равносильны они вашим или нет.

Как и сама учетная запись root, программы с установленным битом setuid полезны, но опасны для применения. Любой кто способен ниспровергнуть или модифицировать setuid программу владелец которой root, может использовать ее для запуска командного интерпретатора shell с привилегиями пользователя root. По этой причине, при открытии файла для записи автоматически отключает setuid бит на большинстве Unix. Многие атаки на безопасность Unix пытаются использовать ошибки и уязвимости в setuid программах для их разрушения. Поэтому здравомыслящие системные администраторы особенно настороженно относятся к этим программам и неохотно их устанавливают.

Выше, во время обсуждения прав доступа, мы упустили пару важных деталей, а именно, какая группа владеет и какие права присваиваются файлу и каталогу когда он впервые создается. Вопрос группы спорный, пользователи могут быть членами нескольких групп, но одна из них (обусловленная в записи пользователя в /etc/passwd) является группой установленной по умолчанию (default group) для этого пользователя и обычно она и указывается в для вновь созданного файла.

История с начальными битами прав доступа немного более сложная. Программа создающая файл обычно устанавливает права доступа того кто ее запустил. Однако это можно изменить, поменяв значение переменной пользовательского окружения называемой umask. Umask определяет какие биты прав доступа при создании файла отключить; наиболее распространенное и устанавливаемое по умолчанию на большинстве систем значение это -------w- или 002, которое выключает бит права изменения миром. За дополнительными подробностями о переменной umask можно обратиться к страницам руководства man вашего shell.

Начальное занчение группы для каталога также немного сложнее. На некоторых Unix для нового каталога устанавливается группа создающего его пользователя (это соглашение в стиле System V); на других он наследует группу родительского каталога (соглашение в стиле BSD). В некоторых современных Unix, включая Linux, последнее поведение может быть выбрано установкой для каталога атрибута set-group-ID (chmod g+s).

10.6. О неисправностях файловых систем

Ранее я упоминал что файловые системы могут быть хрупкими. Мы уже знаем что для того чтобы системе добраться до файла надо попрыгать в "классики" и цепочка из каталогов и ссылок i-node может быть произвольно длинной. Теперь допустим на вашем жестком диске образовался плохой участок.

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

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

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

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