Я прохожу курс "Операционная система Unix" и после тестов, вижу в отчете, что этот тест сдало еще 25 человек. Почему так мало, это ведь реально хороший и полезный урок. Здесь естьи теория и практичесские материалы. Сам курс написан хорошо, живым языком. И здесь я получил ответы на вопросы по Linux, которые боялся спросить. Наверное это из-за того, что в названии курса написано не Linux, а Unix и это многих отпугивает. |
Устройства, терминалы и процессы
Устройства
В лекции 7 уже упоминалось, что для управления UNIX-системой довольно малого: выделить на машине линию, способную принимать и получать текстовые данные (по сути, поток байтов) и научить пользователя эти данные в линию вводить и читать их оттуда. Для такой цели стандартом [ 10 ] предусмотрено оконечное устройство (оконечным оно названо потому, что на нем заканчивает путь передаваемая информация) или терминал.
Прежде чем говорить о терминалах, рассмотрим одно специфическое для UNIX понятие, которое нам понадобится в дальнейшем, - понятие устройства (device). Дело в том, что слово "устройство" в UNIX понимается двояко. С одной стороны - это внешнее устройство, то есть некая аппаратная часть компьютера, которая занимается обработкой или хранением данных. Жесткий диск, видеоадаптер, сетевой интерфейс, последовательный порт - все это примеры внешних устройств. Они как-то работают, и система может ими управлять сообразно потребностям; однако пользователю все тонкости работы с внешними устройствами на низком уровне вряд ли понадобятся. Если ему даже и нужен доступ к диску безо всякой файловой системы, то хорошо бы при этом не думать о том, в какие порты ввода/вывода нужно записывать определенные значения, потому что для разных типов оборудования эти значения будут различными. Вспомним, что унификация доступа - задача самой системы, а пользователю следует предоставлять универсальные команды, применимые к любым типам дисков и к любым видам дисковых контроллеров.
Таким образом, если посмотреть с другой стороны, т. е. с точки зрения пользователя, разнообразие устройств должно диктоваться только разнообразием их функциональности. Но и совсем различные устройства должны поддерживать простейшие способы передачи данных, вроде "открыть устройство-прочитать-закрыть" или "открыть устройство-записать-закрыть". Для этих операций уже придумана абстракция: файл. (Есть ли у понятия "файл" определение? Думается, что должно быть. Например, такое: "Файл - это именованная область данных".) Поэтому в UNIX точки доступа к устройствам (чаще говорят просто "устройства" ) размещаются в файловой системе: подобно файлам, устройства имеют имена, в них можно писать и можно из них читать. Иногда устройства называют еще файл-дырками, потому что наглядно можно себе представить устройство в виде дырки в файловой системе: все данные, которые мы записываем в такой файл, проваливаются в него, не занимая места на диске, прямо к драйверу, и читаем мы данные не с диска, а из дырки, куда их драйвер подкладывает. Традиционно устройства (или, что одно и то же, их файл-дырки ) размещаются в UNIX в каталоге /dev (в некоторых системах, например, в Solaris, содержимое каталога /dev - лишь символьные ссылки на реальные устройства, тогда все сказанное ниже относится именно к ним), хотя создать устройство и пользоваться им можно в любом месте файловой системы, которая поддерживает файл-дырки.
Команда ls -l /dev покажет нам содержимое этого каталога (в некоторых системах - весьма внушительное). Не будем подробно рассказывать обо всем, что можно там увидеть (кое-что описано в лекции 10), но отметим, чем отличается формат выдачи ls для файл-дырки от того, что выводится для обычного файла. Вместо символа в самом начале строки ls пишет c или b, а в том месте, где ls показывала размер, стоят два числа. Буквы c и b обозначают символьное и блочное устройство соответственно ( устройство, обмен данными с которым производится по одному символу или только блоками определенных размеров; это разделение чисто условное: в некоторых системах, например в FreeBSD, все устройства в конце концов сделали символьными), а два числа вместо размера - это так называемые старший и младший номера устройства (major device number, minor device number).
Старший номер устройства указывает, какой драйвер будет обрабатывать запросы на чтение из этого файла или запись в него, младший - к какому из нескольких внешних устройств или разделов идет обращение, а также один из возможных методов такого обращения. Например, в FreeBSD5.2 все звуковые устройства имеют старший номер 30, а младшие номера у них различны: 0 - /dev/mixer0 (микшер), 3 - /dev/dsp0.0 (оцифрованный звук), 4 - /dev/audio0.0 (звук в формате "sparc audio") и т. п. Отсюда следует, что называться устройства могут как угодно, потому что действительную информацию система получает именно из этих номеров.
Символьные ссылки
Вполне возможно, что ls -l /dev выдаст вам среди прочего нечто похожее на
lrwxr-xr-x 1 root wheel 5 Jun 2 20:19 /dev/cdrom -> hdc
Что это за тип файла l, и что это за " -> " ближе к концу строки? Так ls обозначает символьную ссылку - особый вид файла, не содержащего ничего, кроме имени другого файла. Когда ядру приходит запрос на открытие символьной ссылки, оно для начала подменяет ее имя именем файла, в ней находящимся. Если этот файл в свою очередь тоже символьная ссылка, операция повторяется до тех пор, когда очередное имя не окажется чем-то иным (например, файлом) или вообще будет отсутствовать (тогда произойдет ошибка). Из сказанного ls следует, что вместо /dev/cdrom будет взят файл /dev/hdc. Кстати, чтобы попросить ls проделать эту работу самостоятельно, можно добавить ключ -L, тогда для /dev/cdrom выведутся характеристики файл-дырки /dev/hdc. Конечно, создавать символьные ссылки может любой пользователь и в любом месте, где ему разрешено что-либо создавать. Вы можете запросто сказать что-нибудь вроде
$ cd $ ln -s /tmp/mytmpdir tmp
причем /tmp/mytmpdir вовсе не обязан существовать! До тех пор пока вы не обращаетесь к этому файлу, его отсутствие никого не беспокоит. Можно теперь создать /tmp/mytmpdir
$ mkdir /tmp/mytmpdir
и бесцельная ссылка tmp в вашем домашнем каталоге начнет указывать на вновь созданный.
Индексные дескрипторы и жёсткие ссылки
Если символьная ссылка указывает на существующий файл, у того образуется как бы два имени - "настоящее" и "ссылочное". Так или иначе, мы всегда имеем дело с двумя различными объектами: специальным файлом-символьной ссылкой и любым (в том числе - отсутствующим) объектом файловой системы, на который эта ссылка указывает. На самом деле внутри одной файловой системы у каждого файла может быть сколько угодно "настоящих" имён в каких угодно каталогах!
Дело в том, что уникальный идентификатор файла - не имя, и не полный путь, а так называемый индексный дескриптор ( i-node ). Индексный дескриптор - это некое целое положительное число, присваиваемое каждому файлу в файловой системе (индекс), и служебная область данных, описывающая свойства этого файла (права доступа, тип, размещение на диске и т. п.). Имя же файла - не более, чем часть записи в каталоге, связывающая его и индексный дескриптор. Собственно, файловой системой в UNIX как раз и называется область диска, содержащая систематизированные при помощи индексных дескрипторов данные. При обращении к файлу ядро первым делом выясняет, в какой файловой системе он находится, а затем - какой inode ему соответствует. Таким образом, в разных файловых системах могут встречаться дескрипторы с одинаковыми индексами.
Такое дополнительное имя называется жёсткой ссылкой на файл (hard link), Собственно, все имена файла - жёсткие ссылки на него, они равноправны независимо от времени возникновения. Создать жёсткую ссылку на файл (завести ещё одно имя) можно с помощью команды ln (link). Параметры эта команда имеет такие же, как и cp, но копирования данных не производит, а только создаёт в соответствующем каталоге новое имя для существующего файла. В нашем примере мы создаём два файла, заводим жёсткую ссылку на первый и убеждаемся, что и содержимое, и значение i-node (первое поле команды ls -il ) у файла first и third совпадают. Стоит обратить внимание и на третье поле этой команды - в нём как раз и показано количество имеющихся ссылок на файл.
$ echo "First file" > first $ echo "Second file" > second $ ln first third $ ls -il first second third 706579 -rw-r--r-- 2 george staff 11 авг 25 23:35 first 709607 -rw-r--r-- 1 george staff 12 авг 25 23:35 second 706579 -rw-r--r-- 2 george staff 11 авг 25 23:35 third $ cat first second third First file Second file First file $ rm first $ ls -il second third 709607 -rw-r--r-- 1 george staff 12 авг 25 23:35 second 706579 -rw-r--r-- 1 george staff 11 авг 25 23:35 third
Как видно из примера, удаление ( rm ) применяется к имени файла, и если на него было больше одной ссылки, удаляется только имя, а счётчик ссылок уменьшается на единицу. И только когда счётчик ссылок доходит до нуля, место, занимаемое файлом, освобождается. Кстати, если файл с единственным именем был открыт, и после этого удалён, с ним всё ещё можно работать - до тех пор, пока он не закрыт. При этом индексный дескриптор занят. А вот имени не задействовано ни одного. Таким методом пользуются программы, не желающие, чтобы в их временные файлы заглядывал кто бы то ни было.
Жёсткие ссылки возможно заводить только на файлы. Если представить себе жёсткую ссылку на каталог, помещённую в его собственный подкаталог, и вспомнить, что оба этих имени - "настоящие", то становится понятна вся опасность ссылок на каталог. В самом деле, когда команде ls -R остановиться при рекурсивном обходе такого каталога?