Pull to refresh

Inferno Часть 0: пространства имён

Reading time 10 min
Views 5.4K
Original author: Pete Elmore
FAQ: Что такое OS Inferno и зачем она нужна?

Я обещал, но ещё не написал пост о том, как установить и запустить Inferno, и делать невероятные вещи; я раздул его до серии статей, из которых это первая, вводная часть. Я собираюсь немного рассказать о пространствах имён (namespaces). Это критическая часть ОС, и одна из тех вещей, которые сильно отличают Plan 9 и Inferno от того, что сейчас работает на вашем компе.

Inferno малоизвестна, и я не намерен её евангелизировать. Я хочу помочь сократить разрыв между предысторией и практикой, чтобы объяснить как использовать Inferno, и почему она работает так, как работает.

Мне придётся немного отклониться в сторону. Я собираюсь поговорить об эволюции пространств имён, не совсем в хронологическом порядке, скорее в порядке развития возможностей, и потом показать как использовать возможности Inferno.

Содержание



DOS


Помните DOS? У вас были A: и B:, ваши дисководы. Был C:, ваш винчестер, и т.д. У вас была иерархия каталогов на каждом из этих дисков. (Опустим лишние детали.) Вы можете думать об этом как о плоском, верхнеуровневом, одно-буквенном, привязанном к железу пространстве имён. Один диск — одна буква.

Unix, Linux


В Unix, однако, был каталог верхнего уровня, "/". Туда монтировался корневой диск, а все остальные диски монтировались в подкаталоги корневого каталога, в подкаталоги подкаталогов — где бы вы хотели видеть этот диск. Вам не требовалось знать что на каком разделе или диске, если только вы не занимались настройкой системы или на одном из разделов не заканчивалось свободное место. Вы можете думать об этом как об иерархическом пространстве имён, общем для всей ОС.

Это намного более гибкий и мощный подход. Программам и пользователям не требуется знать что на каком диске.

Позднее, в Unix появились файловые системы нового типа: синтетические. Например, /proc. В Linux так же есть /sys, и не редко /dev тоже синтетическая файловая система. Нет физического диска, на котором бы хранились файлы этих файловых систем, но, тем не менее, программам об этом ничего знать не нужно. Файлы видны в пространстве имён так же, как любые другие файлы, и программы не требуется изменять чтобы они смогли читать или писать файлы в этих файловых системах.

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

Дальше есть FUSE, предоставляющая файловые системы в пространстве пользователя. Используя FUSE для взаимодействия с локальным ядром ОС, и реализовав то, для чего вы собирались писать драйвер, вы можете создать сервис любой синтетической файловой системы — без необходимости писать реальный драйвер для ядра ОС. (Я замалчиваю BSD; туда похоже попало меньше фич из Plan 9, хотя в DragonFly разработали несколько интересных идей.)

С другой стороны, поскольку пространство имён общее для всей системы, вам требуется быть root чтобы изменять его. Представьте себе случайного пользователя, который что-то там подмонтировал поверх /sbin, угробив этим даже команду umount. Пользовательские монтирования это мелкое исключение, в каком-то смысле костыль, который принципиально ничего не меняет: вы можете монтировать файловую систему FUSE в любой _свой_ каталог. (Кстати, в Linux есть драйвер для 9P2000, протокола используемого Plan 9 и Inferno.)

Ранее, файловая система могла быть подключена только в одном месте. «Bind mounts» в Linux дают немного больше гибкости — если файловая система (или её часть) уже доступна где-то в пространстве имён, её можно подключить в другое место через mount --bind. Это относительно недавнее добавление, и до ядра 2.6.26 нельзя было подключить одну и ту же файловую систему в одно место в режиме read-write и при этом в другое в режиме read-only.

Plan 9, Inferno


Plan 9 и Inferno взяли несколько больших кусков исторической семантики Unix и выкинули их в окно, выкинули некоторые из ключевых допущений ОС, допущений, которые во многом были подразумевающимися и неявными. Я сейчас говорю про Inferno, но практически всё это так же относится к (и впервые появилось в) Plan 9. Когда я говорю «в Inferno» можете спокойно добавлять в скобках «и в Plan 9». Эти допущения не указаны в каком-то определённом порядке, я их просто для удобства пронумеровал.

Первое допущение, которое было проще всего сломать, и, пожалуй, самое очевидное в ретроспективе — то, что файлы и каталоги в пространстве имён представляют объекты на диске.

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

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

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

Эти три допущения были нарушены в разной степени в Unix-подобных ОС, и с разной степенью успешности. Первое допущение было успешно нарушено в Unix. У вас есть /proc, к примеру, почти во всех Unix. FUSE позволила пользователям монтировать файловые системы, даже скрывать их (не идеально, конечно) от других пользователей, что дало подобие личного пространства имён, почти нарушив третье допущение. Bind mounts дали возможность одной части пространства имён появиться в где-то в другой части, приблизившись к нарушению второго допущения, но требуя root. Union mounts так же пробрались в Unix, вроде бы. Но, за исключением первого допущения, все эти решения не полны. Что если мы начнём с самого начала, не таща за собой багаж Unix?

Поскольку пространство имён теперь у каждого процесса своё (точнее говоря, любой процесс может, но не обязан fork-нуть пространство имён), кто угодно может монтировать что угодно куда угодно, или подключать (bind) что угодно куда угодно, без создания каких либо проблем безопасности. Поскольку точка монтирования может содержать любое количество подмонтированных систем, причём все будут одновременно доступны, появляется возможность накладывать одни файловые системы на другие. Поскольку любая файловая система может быть «настоящей» или «синтетической» пока она использует соответствующий протокол (9P2000 в случае Inferno), что угодно может быть файловой системой и любая программа которая работает с файлами может это использовать.

Многие вещи, которые являются либо хаками, либо кривыми решениями, вдруг исчезают, поскольку в них больше нет необходимости. Очевидно, что многое из того, что делегировалось root, больше не нужно, как и sudo. chroot больше не нужен. Символические ссылки не нужны. Громадное количество встроенных в ядро ОС драйверов не нужны. NSF и /etc/exports не нужны (скатертью дорога). mount -o loop не нужен. mount --bind не нужен. FUSE не нужна. Даже $PATH больше не нужен, и вместе с ним необходимость быть root для установки софта.

… Ну и?


Одна из вещей, которая раздражает меня в документации для Inferno (и Plan 9) — что есть научные статьи, man страницы, исходный код, но почти нет учебников или документов в стиле «howto». Возможно я испорчен Linux-ом, который идёт с HOWTO как готовить кофе. Начать — непростая задача, особенно если ты не знаешь достаточно о системе чтобы использовать систему для изучения самой себя. Ты пытаешься, но там незнакомый шелл который запускает незнакомые команды, и man-страницы написанные как справочник, не особо помогают.

Так что я могу оценить документ, пытающийся ответить на вопрос «Ну и? Я слышал заманчивые обещания и раньше. Как я могу это использовать?» и я собираюсь объединить всё это несколькими конкретными примерами, поясняя что происходит.

Наконец, что-то что вы можете набрать


Помните все эти вещи, которые больше не нужны? Каждая из них была заменена чем-то лучшим, а некоторые из них несколькими вещами, каждая из которых лучше. Я собираюсь (для простоты) игнорировать аутентификацию в этих примерах, но скажу, что у вас есть выбор методов аутентификации и шифрования в Inferno.

root не нужен для монтирования

Это довольно просто:
bind '#p' /n/prog

Это монтирует файловую систему prog (аналог /proc) в /n/prog. Кстати говоря, вы можете управлять, отлаживать, и делать всё что обычно с запущенными процессами через файловую систему /prog, точно как в Unix. Разница в том, что если вы локально подмонтируете /prog удалённой машины, вы сможете делать все эти вещи с удалёнными процессами без всякой ssh и даже без запущенного отладчика на удалённой машине. Да, вы сможете локально выполнить kill 15 и это убьёт процесс 15 на удалённой машине.

mount -o loop и FUSE не нужны

У меня есть кучка .iso файлов на моём компе. Предположим, они находятся в /n/cds, и я хочу подключить один из них:
; 9660srv /n/cds/dfly-i386-3.0.2_REL.iso /n/dfly
; ls /n/dfly

Сейчас текущий процесс и его потомки могут видеть содержимое этого CD. Ничего особого не требуется; 9660srv(4) знает как читать файловую систему ISO-9660 с одной стороны и поддерживает протокол 9P2000 с другой.

Inferno так же идёт в комплекте с, например, tarfs(4), которая трактует tar-архив как read-only файловую систему.

Драйвера в ядре не нужны

Ну, большинство. Те, которые не просто экспортируют файловую систему, и наконец-то можно будет забыть про ioctl(). Драйвера предоставляемые ядром можно увидеть в файле /dev/drivers, и это довольно краткий список, более краткий, чем вывод lsmod на типичной машине с Ubuntu или даже Arch.

Там, где вам бы потребовался драйвер ядра для поддержки новой файловой системы в большинстве ОС, Inferno не нуждается в modprobe (и таким образом в правах root) и не трогает ядро чтобы добавить новую файловую систему. Вы можете получить поддержку ext2 (read-only) скачав ext2fs, точно так же как ядру не требовалось знать о ISO-9660 в примере выше.

chroot не нужен

Поскольку процесс может создать для себя пространство имён, всё, что может быть опасным показывать не доверенному процессу может быть отмонтировано от пространства имён, и системный вызов pctl(2) может быть использован для запрета процессу монтировать драйвера. Экстремальный пример которые отмонтирует всё (и поэтому не сможет сделать ничего кроме использования встроенной в шелл функциональности):
; load std
; pctl newns
; pctl nodevs
; unmount /
; ls /
sh: ls: './ls' file does not exist

Конечно, нужно действовать немного аккуратнее чем просто отмонтировать всё если вы хотите чтобы получилось что-то полезное, но сама идея проста.

Так же вы можете сделать временную песочницу, если хотите, подмонтировав файловую систему в памяти поверх корневого каталога:
; mount -bc {memfs -s} /
; echo Mad with power! > /asdf

И, конечно, /asdf нигде не появится. (Надо заметить, что это касается только создания новых файлов.)

Симлинки не нужны

bind решает эту задачу предоставляя возможность помещать одни каталоги поверх других. Например, мне нравится набор иконок tinytk больше, чем иконки по умолчанию, так что я перекрываю ими иконки по умолчанию перед запуском оконного менеджера:
; bind -bc /icons/tinytk /icons/tk

Вы даже можете поместить один файл поверх другого:
; echo Hello > some-file
; bind some-file /NOTICE
; cat /NOTICE
Hello

Поскольку симлинки не нужны и отсутствуют в Inferno, проблема циклических ссылок в файловой системе почти исчезает.

$PATH, $LDPATH и права root для установки софта не нужны

Я ненавижу возиться с $PATH. Большие куски моего .bashrc посвящены выяснению кто идёт первым, и не добавлением избыточных путей или путей, которые указывают на бинарники для других архитектур. У меня установлен Plan 9 Port, но я не хочу, чтобы версия Plan 9 man конфликтовала с Linux версией, к примеру.

В Inferno, всё, что вы хотите запускать, находится в /dis (/bin в Plan 9). Если вы хотите запускать программы из другого места, вы просто подключаете его перед или после /dis.
; bind -bc $home/dis /dis

Так что если вы хотите что-то установить, но не можете писать в /dis, установите его куда хотите, и подключите его поверх /dis. sudo не требуется. То же самое касается /lib и /module.

NFS не нужен

Я собираюсь игнорировать аутентификацию (флаг -A) и шифрование, так что мы будем экспортировать что-нибудь не важное: снова memfs(4). Первая машина:
; mount -c {memfs -s} /n/mem
; echo something > /n/mem/asdf
; listen -A 'tcp!*!1234' { export /n/mem & }

Вторая машина:
; mount -A 'tcp!thefirstmachine!1234' /n/remotememfs
; cat /n/remotememfs/asdf
something

Поскольку большинство команд файл-серверов могут работать через stdin/stdout вместо подключения к точке монтирования, файловую систему даже не требуется локально монтировать чтобы сделать её доступной по сети:
; styxlisten -A 'tcp!*!1234' {memfs -s}

И на второй машине:
; mount -Ac 'tcp!thefirstmachine!1234' /n/remotememfs

Команды listen(1) и dial(1) это просто удобные обёртки для взаимодействия с файловой системой /net, которая является интерфейсом в сеть для Inferno. Сокеты в Unix обрабатываются библиотекой BSD sockets (с соответствующими системными вызовами) и значительно сложнее в использовании. Вы можете думать о listen и dial как об аналоге netcat. styxlisten это то же самое, только ожидает передавать протокол 9P2000 (называвшийся так же Styx пока его не приняли в Plan 9) вместо потока байт.

Мощные примитивы означают, что вы никогда не пожалеете


Всё это достигается несколькими короткими командами, которые сами по себе являются просто обёртками вокруг системных вызовов Inferno. У вас есть bind(1), mount(1), и unmount(1). Если вам нужна интроспекция вам поможет ns(1).

Представление всех объектов ОС как файловых систем означает, что программы вроде cat, sed и echo могут быть использованы для, к примеру, доступа к сети используя файловую систему ip(3). ftpfs(4) позволяет использовать ls и cp без интерактивного клиента, что упрощает написание скриптов (нет необходимости в перенаправлении через FTP клиент). По сути, вашим скриптам вообще нет нужды знать, что они работают с FTP сервером а не с обычным файлом на диске. zipfs позволяет вам подмонтировать .zip файл. Комбинируя их, вы можете подмонтировать .iso, который внутри .zip, который на FTP сервере, и потом скопировать из него отдельные файлы.

Где-то в будущем


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

Управление всеми этими ресурсами (диском и CPU, в частности) уже большая проблема. Синхронизация файлов, синхронизация контактов, и т.д. Если у вашего телефона не хватает ресурсов чтобы что-то обработать, вам нужно идти к обычному компу (физически или через ssh). Если вы хотите посмотреть фильм на телефоне, вам необходимо его туда скопировать. Что вы делаете если читали статью на телефоне и решили продолжить чтение на ноутбуке? Посылаете себе email или IM? (Это всё ещё лучше, чем DBUS, но это отступление.)

Я не думаю, что так будет и дальше. В качестве временного решения можно отдать все свои данные Google, Facebook, или любому «облачному» сервису, но такое решение оставляет желать лучшего (и перечисление причин это другое отступление).

Программное решение проблемы управления вычислительными ресурсами и объединения всех этих машин (локальных и удалённых) неизбежно. По крайней мере в данный момент я вижу Inferno лучшим кандидатом на роль платформы, которая сделает всё это возможным. Если это и не полностью объясняет, почему я вдруг влюбился в эту систему, то, по меньшей мере, делает это частично.

Продолжение следует


Это описание очень поверхностно. «Всё является файловой системой» это только одна из великих идей, на которых построена Inferno.
Tags:
Hubs:
+31
Comments 32
Comments Comments 32

Articles