<<<предыдущий список следующий>>>

Это - копия документа, находившегося на http://dz.ru. Авторские права, если не указано иначе, принадлежат Дмитрию Завалишину и/или Евгении Завалишиной. Все изменения, внесенные мной, находятся в этой рамочке.Пожалуйста, прочитайте disclaimer.


04 Февраля 1999

Поднятая тема весьма многогранна. Стоя под душем, я уже обдумывал было, как бы из нее поаккуратнее вынырнуть, но потом решил - пусть ее. В конце концов, файловые системы - это довольно интересно (по крайней мере, все, кто был у меня на выходные в гостях, про эти выпуски онлайна вспомнили:), а я в последнее время маловато внимания уделял софту. Надо наверстывать. :-)

Итак, файловая система - это не только ценное дисковое пространство, но и интерфейс. Логически полная методика доступа к объекту по имени файл, то есть к именованному потоку байт на внешнем носителе.

Конечно, есть еще вызовы для работы с каталогами и вызов для создания файла (creat), но создавать можно и через open, а про каталоги я тут не говорю по очевидным ниже причинам.

Что можно сделать с файлом? В свое время Юникс выкристаллизовал из накопленного другими ОС опыта "великолепную пятерку" системных вызовов для работы с файлом - open, close, read, write, seek. Этими пятью операциями ограничиваются все основные действия с файлом. Его можно открыть (заключить с ОС договор о том, что данный процесс с этого момента имеет право работать с данным файлом), закрыть (спасибо, файл более не нужен), читать, писать и устанавливать позицию в нем, начиная с которой будет произведено следующее действие.

Правда, этого хватило не на все - добавился ioctl, но о нем - позже.

При создании Юникса кто-то мудрый и ленивый обратил внимание, что понятие "именованная последовательность данных" применимо не только к дисковым файлам, но и к самим дискам целиком! А что? Диск - последовательность байт. Правда, заранее определенного размера. Его можно читать и писать - к примеру, утилиты fdisk и format в MS DOS и disklabel/newfs в Unix работают с диском именно как с большим мешком байт - файлами они не интересуются. Утилиты fsck и chkdsk файлами интересуются, но примерно с позиций хирурга - то есть читать/писать они файлы не собираются, а, опять же, работают с диском как с единым куском данных.

Для зануд - имена файлов, девайсов, людей и зверей - условные. Про /dev/r* мне тоже рассказывать не надо. :-)

Значит, есть смысл предоставить к диску такой же интерфейс, как и к файлу - пусть его тоже будет возможно открыть (open("/dev/wd0",...) дает доступ к первому IDE винчестеру в машине), позиционироваться в нем (lseek(512) - "встать" на начало второго сектора диска), читать его и писать обычными read/write. Так в Юниксе и было сделано. Оказалось, что это крайне удобно. Весь стандартный системный инструментарий случайно стал применим не только к файлам, но и к дискам, да и программировать стало проще. Командой cp можно скопировать файл (cp /home/dz/letter.txt /home/jane/dz_letter.txt), а можно - весь диск чохом (cp /dev/wd0 /dev/wd1).

Ну, ладно - диск. А что ж остальные внешние устройства? А они тоже похожи на файлы! Магнитная лента? Пожалуйста /dev/mt. Терминал? Вот вам /dev/tty. Модем? Прошу /dev/cua. Хотите звука? Заливайте байтики в /dev/audio. Все стало файлом, ко всему можно добраться через open, read и write. Ну хорошо, read и write. А если я хочу, к примеру, повысить громкость звука в звуковой карте, перемотать магнитную ленту на начало или сбросить линию DTR у модема, чтобы переинициализировать его? Как дать устройству нестандартную команду? Добавить в ОС тысячу новых системных вызовов на все случаи жизни?

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

Вернемся на минутку к файловым системам. В Юниксе имя файла не включает в себя имени диска, на котором файл находится. Вместо этого в Юниксе существует операция так называемого монтирования - "пристегивания" диска к некоторой ветке дерева файловой системы. Когда система стартует, она располагает одним единственным пустым каталогом /, в котором нет ни шиша. И быть не может - диски еще не доступны. Система монтирует загрузочный диск на каталог / - это значит, что теперь полные имена файлов, начинающиеся на /, то есть все на данный момент, будут искаться системой на загрузочном диске. Диск этот (ну или раздел диска - не важно) мал и содержит только жизненно важную часть ОС. Но есть на нем, как правило, есть пустой подкаталог /usr. В процессе загрузки выполняется команда монтирования основного рабочего диска на каталог /usr. Это означает, что отныне имена файлов, начинающиеся с /usr будут относиться не к загрузочному, а к рабочему диску.

Таким образом, формируется единое дерево каталогов, разные части которого находятся на разных дисках. Или на разных машинах - операция подсоединения сетевого диска выглядит точно так же. В современных Юниксах в виде файловых систем делается все больше и больше интерфейсов к самым разным вещам. Посредством традиционной файловой системы можно обращаться к файлам на диске в юниксовском формате, посредством файловой системы dosfs можно работать с дисками в формате FAT, nfs позволяет обращаться к файлам на других машинах, а procfs предоставляет файловый интерфейс к списку процессов и их атрибутам. То есть командой ls /home/dz мы посмотрим список файлов в моем домашнем каталоге, а командой ls /proc - список процессов в системе. А командой ls /proc/current - список атрибутов процессов - псевдо-файлов. Каждый из них предоставляет доступ к чему-либо, связанному с данным процессом.

Например, в каталоге /procfs/1 лежат псевдо-файлы, описывающие процесс номер 1. Среди них: mem - "файл", предоставляющий доступ к адресному пространству процесса. Чтение из него выдает текущее содержимое памяти, доступной процессу номер 1. "Файл" regs - регистры процессора данного процесса в данный момент, ctl - средство для управления состоянием процесса. Записав в него команду, процесс можно остановить, запустить, исполнять покомандно...

Понятно, что, имея procfs, написать отладчик или какую-либо системную утилиту для работы с процессами - проще простого.

Этот самый procfs я описал лишь для примера. Существует масса других интересных применений этой методике, методике доступа к не-файлам посредством а-ля файлового интерфейса. А может быть и к файлам, но не локальным. Тот же nfs, или вот еще - ftpfs - файловая система, которая позволяет работать с файлами на каком-либо ftp-сервере как со своими собственными. Ну, конечно, с учетом того, что скорость доступа ограничена скоростью канала.

Реклама
knopka.gif (7475 bytes) Вам необходим качественный цветной монитор размером в 42 дюйма? Тогда вам нужны мультимедийные плазменные мониторы нового поколения от NEC для презентаций PlasmaSync 4200W и PlasmaSync 3300 - диагональ от 33" до 42", толщина от 3,5" до 5", настольные и настенные модели с сенсорным дистанционным управлением.

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

Представим себе, как в этой схеме реализуется что-нибудь типа registry. Итак, требования к registry: это должна быть файловая система (а это, несомненно, файловая система), предназначеная для хранения крайне коротких файлов, обращение к которым должно быть крайне быстрым. Исходя из этого, продумывается методика хранения данных (ну, к примеру, делается почти обычная файловая система, но пространство "файлам", то есть записям registry, выделяется кусочками по 8 байт, а не кластерами по килобайту, плюс все индексируется). На диске для нашей registryfs выделяется необходимое место (или же она целиком помещается в файл - юникс и это позволяет), а сама она монтируется в подкаталог /registry нашего файлового дерева.

Что мы имеем? Все плюсы специализированного способа хранения данных и все плюсы генерализованного метода доступа к ним посредством традиционного и всем известного интерфейса. Далее, поскольку в Юниксе существуют так называемые "линки", которые представляют собой просто ссылки из одной ветви дерева файлов на другую, вполне возможно каждому продукту в каталоге, куда он проинсталлирован держать "пристегнутой" свою же ветку registry. Пусть, скажем, фотошоповская информация лежит в /registry/LOCAL_MACHINE/SOFTWARE/AdobePhotoshop/5.0, а сам он - в /usr/local/photoshop. Тогда элемент по имени ApplicationPath будет доступен и как /registry/LOCAL_MACHINE/SOFTWARE/AdobePhotoshop/5.0/ApplicationPath, так и /usr/local/photoshop/registry/ApplicationPath.

Теперь немного пинков. Определенную непоследовательность в Юниксе допустили с сетью. К примеру, cd-rom и звуковая карта в нем доступны как файл, а сетевая карта - нет. Почему - непонятно. То есть для того, чтобы послать пакет по сети или учинить соединение с http-сервером, нужно не специальный файл открыть, а создать и присоединить сокет. Другое дело, что после создания сокет вполне канает за файл - то есть если какой программе его подсунуть, то она, "думая", что это - файл, будет из него читать и писать ничего особо не замечая. Но вот с помощью open() сокет создать нельзя. Увы, в ДОС-OS/2-Windows все еще хуже - сокет в них вообще принципиально отличается от дескриптора файла и они невзаимозаменяемы никак и никогда. Причем, как я уже писал, для этого нет технических причин - сами ОС это позволяют, кажется, начиная с MS DOS 3.20.

Существует масса предложений по исправлению этого недостатка. Например, сделать эдакую файловую систему, имена "файлов" в которой будут соответстовать адресам машин. Ну, к примеру, попытка открыть файл по имени /socket/ru/dz/www/80 приведет в такой ФС к порождению сетевого соединения с WWW-сервером, который обслуживает www.dz.ru (80 - это номер порта). Вариант - /socket/www.dz.ru/80, или /socket/www.dz.ru/http. Идея ясна, а реализовать можно всяко.

Увы, несмотря на очевидную естественность и удобство такого интерфейса к сети, он как-то "в промышленных масштабах" не существует. Хотя порывались его делать не раз и не в одной ОС.

Читатель спрашивает - что, мол, Завалишин, все чай, да чай пьешь? Почто не пиво? Отвечаю. Пиво я тоже иногда пью. Летом - чаще, зимой - реже, во время работы - почти никогда. По моим наблюдениям, после пары бутылок пива вредно садиться не только за руль, но и за клавиатуру. А вот после полулитровой коллекционной кружечки чая - самое оно. :-) Пиво же идеально пить, уехав в Питер - там, вдалеке от дел, можно расслабиться, сесть с друзьями в "Гамбринусе" и, не думая о теме завтрашнего номера, врезать темненького. :-)