POWERMAN
"In each of us sleeps a genius...
and his sleep gets deeper everyday."

Один из краеугольных камней архитектуры Inferno - юниксовая идея с файлами-устройствами доведена до предела: в Inferno файлами представлено абсолютно всё. Например, в Inferno нет понятия "сокет".

Файлы.

В 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 с этого сервера. И всё - остальная часть проекта даже не заметит что этот модуль выполняется на другом сервере!

Namespaces.

Пространства имён (namespace) в Inferno аналогичны тем, которые используются во многих языках программирования… только в Inferno они применяются к файлам и каталогам.

Фактически привилегии и возможности программы под Inferno ограничены тем, к каким файлам (ибо любой ресурс = файл) она имеет доступ. Манипулируя namespace можно для каждого приложения создать свою, изолированную (а-ля chroot) среду, со своими устройствами в /dev (как выше в примере с удалённым терминалом), со своими сетевыми картами в /net (как выше в примере с NAT), etc.

К примеру, в винде есть такая фича - вы логинитесь с любого компа в сети и получаете СВОЙ рабочий стол и СВОЙ каталог "мои документы". В Inferno вы, залогинившись с любого терминала и имея доступ к своим ключам/сертификатам можете манипулируя namespace создать 100% ту же самую среду, которую вы имеете на своём основном компе. И для реализации этого никаких специальных "фич" в Inferno нет - обычные команды mount, bind и протокол Styx.

Возможно всё это звучит не очень принципиально, но принцип работы с приложениями кардинально изменяется - обычно мы пытаемся добиться того, чтобы приложение работало в самых разных условиях (что значительно его усложняет), а в Inferno мы для каждого приложения с помощью namespace, команд mount и bind создаём именно ту среду, на которую расчитано это приложение.