В Inferno файлами представлены не только устройства (аналог /dev/) и
процессы (аналог /proc/), но и такие вещи как DNS resolver, сокеты и
переменные окружения (environment).
Например, для того, чтобы открыть tcp-соединение на сайт www.habrahabr.ru,
нужно проделать следующие операции:
-
открыть файл /net/cs
-
записать в него строку tcp!www.babrahabr.ru!http
-
считать из него ответ (это будет строка /net/tcp/clone 217.147.30.151!80)
-
открыть файл /net/tcp/clone
-
считать из него число (идентификатор этого соединения, далее ID),
при этом в каталоге /net/tcp/ автоматически появится новый подкаталог
/net/tcp/ID/ с файлами ctl, data, status, etc.
-
записать в файл /net/tcp/ID/ctl строку connect 217.147.30.151!80
-
читать/писать файл /net/tcp/ID/data
Пояснения к примерам. Примеры для краткости приведены на sh, а не Limbo.
-
";" - это приглашение sh.
-
">[1=0]" это перенаправление STDOUT на STDIN.
-
"<>/path" это открытие STDIN на чтение+запись в /path.
-
"read" читает из STDIN и выводит на STDOUT заданное кол-во байт.
-
"`{…}" это выполнить команду и вернуть её вывод.
; { echo -n 'tcp!www.habrahabr.net!http' >[1=0]; read -o 0 8192; } <>/net/cs
/net/tcp/clone 209.85.84.157!80
; { id=`{read}
echo 'connect 209.85.84.157!80' >/net/tcp/$id/ctl
echo 'HEAD / HTTP/1.0' >/net/tcp/$id/data
echo 'Host: www.habrahabr.ru' >/net/tcp/$id/data
echo >/net/tcp/$id/data
read </net/tcp/$id/data
} <>/net/tcp/clone
HTTP/1.1 200 OK
Date: Sun, 27 May 2007 11:33:42 GMT
Server: Apache/2.0.52 (Red Hat)
X-Powered-By: PHP/5.1.4
Set-Cookie: vsid=3X02X521137108; expires=Fri, 25-May-2012 11:33:43 GMT; path=/
Connection: close
Content-Type: text/html; charset=UTF-8
С переменными окружения работа идёт аналогично - есть каталог
/env/, файлы
в котором это имена переменных, а содержимое файлов - значения переменных.
Соответственно создание/удаление файла это создание/удаление переменной
окружения.
Для доступа к информации по процессам используется каталог
/prog/. Причём
абсолютно все операции выполняются через его подкаталоги и файлы - в том
числе отладка (т.е. не нужен сискол POSIX ptrace) и получение информации о
статусе процесса (т.е. не нужны сисколы wait/waitpid).
Работа всех этих виртуальных файлов обеспечивается разными средствами -
например /net/tcp/ и /env/ реализованы через драйвера Inferno, а DNS
ресолвер /net/cs реализован обычным приложением.
Такой подход позволил упростить множество вещей:
-
для работы с сетью достаточно обычного файлового API, отдельные функции
POSIX (socket, connect, bind, listen, etc.) стали не нужны
-
аналогично, нет специального API для работы с переменными окружения
(clearenv, putenv, setenv, getenv, etc.)
-
поскольку протокол Styx позволяет расшаривать файлы по сети, то можно
делать, например, следующие трюки:
-
если машина в локальной сети, не имеющая реального IP-адреса,
подмонтирует себе каталог /net шлюза в инет, то она получит прямой
выход в инет без необходимости настраивать на шлюзе штуки типа NAT или
маскарада
-
если на удалённый сервер подмонтировать по сети файлы /dev/cons,
/dev/keyboard и /dev/pointer с рабочей станции, то на сервере можно
будет запускать графические приложения которые будут управляться с
терминала рабочей станции - и всё это без специального протокола а-ля
X-Window, со встроенной (в Styx) авторизацией, аутентификацией и
шифрованием
-
если на локальную машину подмонтировать каталог /prog (аналог /proc) с
удалённого сервера, то можно будет локальным отладчиком отлаживать
процессы выполняющиеся на удалённой машине - и отладчик об этом даже
знать не будет, потому что он просто работает через файлы в /prog
Но, с моей точки зрения, гораздо важнее не то, что отпала необходимость в
куче сисколов, а то, что "объектов" особенности поведения которых
необходимо знать для качественного программирования стало намного меньше!
К примеру, в юниксах у файлов одни особенности, у специальных файлов
(юникс-сокеты, пайпы, некоторые устройства) другие, а у сокетов третьи -
а в Inferno всё это одинаковые файлы с одинаковым поведением.
"Правильная" программа в Inferno должна писаться не в стиле традиционных
юниксовых утилит (читаем STDIN, пишем STDOUT), а в стиле файлового сервера
Styx. Иными словами входом/выходом у такой утилиты должен быть не
STDIN/STDOUT, а виртуальный файл или каталог с файлами а-ля /net/cs или
/net/tcp/.
Это позволит очень легко строить распределённые системы. Например,
предположим в нашем проекте есть модуль который что-то считает. Он
реализован в виде отдельного процесса, который экспортирует файл ./calc,
в который можно писать задания и считывать из него результат. Если
возникает потребность ускорить вычисления перенеся эту подзадачу на
отдельный, более мощный сервер, то достаточно двух шагов: запустить этот
модуль на другом сервере; подмонтировать файл ./calc с этого сервера. И
всё - остальная часть проекта даже не заметит что этот модуль выполняется
на другом сервере!
Пространства имён (namespace) в Inferno аналогичны тем, которые
используются во многих языках программирования… только в Inferno они
применяются к файлам и каталогам.
Фактически привилегии и возможности программы под Inferno ограничены тем,
к каким файлам (ибо любой ресурс = файл) она имеет доступ. Манипулируя
namespace можно для каждого приложения создать свою, изолированную (а-ля
chroot) среду, со своими устройствами в /dev (как выше в примере с
удалённым терминалом), со своими сетевыми картами в /net (как выше в
примере с NAT), etc.
К примеру, в винде есть такая фича - вы логинитесь с любого компа в сети и
получаете СВОЙ рабочий стол и СВОЙ каталог "мои документы". В Inferno вы,
залогинившись с любого терминала и имея доступ к своим ключам/сертификатам
можете манипулируя namespace создать 100% ту же самую среду, которую вы
имеете на своём основном компе. И для реализации этого никаких специальных
"фич" в Inferno нет - обычные команды mount, bind и протокол Styx.
Возможно всё это звучит не очень принципиально, но принцип работы с
приложениями кардинально изменяется - обычно мы пытаемся добиться того,
чтобы приложение работало в самых разных условиях (что значительно его
усложняет), а в Inferno мы для каждого приложения с помощью namespace,
команд mount и bind создаём именно ту среду, на которую расчитано это
приложение.