Думаю, общей информации по Inferno уже достаточно, и можно перейти к главному вопросу: что из себя представляет Inferno изнутри, с точки зрения программиста? В чём заключается взаимодействие программиста со средой предоставляемой Inferno? Сколько нюансов поведения и разных видов сущностей должен держать в голове программист в Inferno?
Например, под линухом для эффективного и качественного программирования нужно держать в голове как минимум несколько очень толстых томов Стивенса, начиная с APUE (Advanced Programming in the UNIX Environment, Second Edition, 925 страниц, обошлась мне в $75+доставка с амазона). И слава Богу, что такая книга вообще есть в природе, без неё было бы совсем туго, кстати!
А всё потому, что под линухом мы имеем множество разных сущностей (файлы/каталоги, процессы, терминалы, сигналы, нити, пайпы, сообщения, семафоры, разделяемая память, сетевые сокеты, unix сокеты, псевдо-терминалы, etc.), и у каждой море нюансов поведения (блокирующий I/O, неблокирующий I/O, асинхронный I/O, мультиплексирование I/O, fcntl/ioctl, etc.) в разных условиях! Насколько я понимаю, под виндой ситуация ещё хуже т.к. плюс к примерно аналогичному зоопарку добавляется по несколько версий API, которые Microsoft называет "новыми революционными технологиями" и выпускает раз в 2-3 года (у Джоэля Спольски была хорошая статья на эту тему).
Так вот, в Inferno таких сущностей ровно ТРИ: нити, каналы и файлы. И нюансов поведения у них значительно меньше: файлы поддерживают исключительно блокирующий I/O без возможности мультиплексирования, каналы тоже блокирующие но их можно мультиплексировать, файлы все "обычные" и никаких fcntl/ioctl в природе нет, etc. Причём этих трёх сущностей хватает, чтобы покрыть практически всю ту функциональность, для которой в UNIX-системах развели этот зоопарк!
1-я сущность: процесс/нить.
В Inferno нет отличия между процессами и нитями. Изолирование и группирование нитей осуществляется через namespaces. Вот сравнительная таблица свойств процессов Inferno по сравнению с процессами линуха:
| Linux | Inferno | |
|---|---|---|
| Open files | + | + |
| UID, GID, EUID, EGID | + | ? |
| Supplementary group IDs | + | |
| Process group ID | + | + |
| Session ID | + | |
| Controlling terminal | + | |
| SUID and SGID flags | + | |
| Current working dir | + | + |
| Root dir | + | + |
| umask | + | |
| Signal mask and dispositions | + | |
| The close-on-exec flag for open files | + | |
| Environment | + | + |
| Attached shared memory segments | + | |
| Memory mappings | + | |
| Resource limits | + | |
| File locks for open files | + | |
| Pending alarms | + | |
| Namespace | + |
Что касается UID/GID/EUID/EGID, то UID, теоретически, в Inferno есть. А практически его как бы и нет - разделение прав доступа к ресурсам обеспечивается сертификатами, протоколом Styx, и namespace… а имя юзера никакой роли в этом процессе не играет и используется, насколько я понимаю, исключительно для определения имени домашнего каталога. Возможно я что-то не уловил, но похоже что Inferno под типовые определения однопользовательской/многопользовательской системы просто не попадает, это нечто иное. :)
Для управления практически всеми (кроме текущего каталога) свойствами процесса Inferno служит один, довольно простой сискол pctl.
Процессы в Inferno можно: порождать (оператором spawn в Limbo), изменять их свойства (сисколом pctl), завершать (оператором exit в Limbo) и … и всё, в общем! По крайней мере в той части, которая касается API Inferno. В принципе кроме этого можно ещё оперировать процессами через файлы в каталоге /prog/, но это уже относится к файловому API.
2-я сущность: каналы.
С каналами всё ещё проще, чем с процессами:
-
их можно создавать (как переменные в Limbo типа chan of что-то)
-
можно удалять (когда переменная выходит из области видимости либо в неё присваивают nil)
-
можно с помощью операторов Limbo chan← и ←chan атомарно, в блокирующем режиме принимать/передавать данные между нитями
-
можно мультиплексировать ввод/вывод в каналы
Этой функциональности достаточно, чтобы заменить все виды синхронизации и IPC существующие в линухе.
3-я сущность: файлы/каталоги.
Работа с файлами в Inferno не намного проще, чем в линухе - за исключением не нужных fcntl и ioctl API практически идентичное: mount, bind, chdir, open, dup, read, stat, diropen, dirread, etc…
Жизнь, правда, заметно упрощается за счёт того, что весь I/O в файлы только блокирующий, и мультиплексирования тоже нет - если что-то из этого арсенала необходимо это решается выделением блокирующих задач в отдельные нити (что, кстати, стимулирует более продуманную архитектуру приложения).
В принципе в Inferno ещё есть такой рудимент как пайпы. Но, в отличие от линуха, где они используются как одно из основных средств IPC, в Inferno пайпы это что-то типа workaround-а для случая, когда кому-нить (например, библиотечной функции) нужен файловый дескриптор, а вам хочется вместо дескриптора реального файла подсунуть ей "виртуальный" дескриптор ведущий не в реальный файл, а в ваш код.
Ещё добавляется работа со специфичными фичами Inferno - namespaces, поддержка протокола Styx и его сертификаты, авторизация, аутентификация и шифрование. Но эта часть работы обычно выполняется админом в командной строке (или в sh-скрипте запускающем ваше приложение), и никак не усложняет программирование приложения.
И всё?
И всё! Всё остальное это голые вычисления - обсчитывание данных в переменных: поддержка разных форматов файлов, баз данных, сетевых протоколов, etc. Это всё прикладуха, и никак не усложняет среду в которой работают программы и не вводит новых сущностей.
Бонус.
На закуску я повторю список сущностей линуха и покажу чем все они заменяются в Inferno:
| Linux | Inferno |
|---|---|
| файлы/каталоги | файлы/каталоги |
| процессы | нити |
| терминалы | - |
| сигналы | каналы |
| нити | нити |
| пайпы | - (тот workaround не считается) |
| сообщения | каналы |
| семафоры | каналы |
| разделяемая память | каналы |
| сетевые сокеты | файлы |
| unix сокеты | - (надеюсь, скоро здесь будут стоять "файлы") |
| псевдо-терминалы | - |