📜 ⬆️ ⬇️

Architecture OS Inferno - 1

Immediately I warn you that I'm not going to do a full overview of the architecture. First there is the original documentation where everything is described in detail. And secondly, I still do not know Inferno so well as to undertake writing a detailed description of the architecture. But I’ll tell you about the “tricks” of architecture, this is the most interesting.

Programming under Inferno is possible in two languages ​​- Limbo and sh. On sh, you can do almost everything the same as on Limbo, only ... very slowly. From the point of view of interaction with the system architecture, there is practically no difference between them, so I’ll describe further from the point of view of programming on Limbo.

Programs and Libraries


In Inferno there is no difference between the program (application, script) and the library (.so - shared object, .dll). All programs on Limbo are modules, and can be used in this quality by any other program / module. Those. one “program” can at any moment load ANY other “program” into memory as a normal library and start calling its functions. And having finished calling the necessary functions, it can unload the module that has become unnecessary from memory (loading / unloading occurs at run time, and not when the program is started).

By “programs” in Inferno is meant such modules that are compatible with the “Command” interface, which means that the module has a function called init that takes two parameters (graphics context and argument list) and returns nothing.
')
You know what happens when you type the name of a program to run on the sh command line — for example, ls or pwd? A funny thing happens - sh just finds a file on the disk with the module byte-code whose name you typed, loads it and calls its init function. And when init is completed, sh unloads this module from memory and waits for the next command to be typed. :) (To be honest, in practice, everything is a bit more complicated there, but this is the essence.) Thus, there is no analogue of the whole family of POSIX exec * () syscols in Inferno - they are not needed. :)

Interfaces


This is not the key point, but since we are talking about it ... Limbo is a strongly typed language, type checking is carried out both at the compilation stage and at the execution stage. When you load a module, you get its handler in a variable, and the type of this variable should determine what functions / constants are in this module, what kind of parameters they have, etc. Here is a description of this whole economy and is called a module interface. (A similar scheme is used in Pascal - there is also a separate description of the interface and the implementation of the module separately.)

At the same time, one module can implement several different interfaces (sets of functions / constants). And one interface can have many different implementations in different modules (which is used in the case of the “Command” interface).

And when you load the Limbo module, you need to specify both the path to the file with the implementation (module byte-code) and the interface name (interface descriptions are loaded in the manner of include .h files in C). After that, Limbo can check the compatibility of the implementation and interface specified by you, and if everything is in order, it will return to you the handler of this module having the type of interface you specified.

As for the use of memory, everything is done correctly - one copy of the code of the loaded module is stored separately for all Inferno processes, and each module has a separate memory for storing the stack, global variables, etc. this module. When you unload your handler, a part of the memory occupied by its copy of global variables / stack is freed, and when the last handler is freed, the module code itself is unloaded from memory.

Processes and threads


There is no difference between a process and a thread in Inferno. In essence, all Inferno processes are very light threads.

How the Inferno threads are mapped to the host OS threads (if Inferno is running in hosted mode under Windows / Linux / etc.) Depends on the implementation of Inferno for this host OS. As I understand it, Inferno uses a mixed model - part of its internal threads, i.e. A single host OS process / thread can contain several Inferno threads, and some of the Inferno threads are mapped onto the one-to-one host OS threads (in particular, this applies to threads that block syscall host OS — for example, reading from a socket).

In essence, running OS Inferno looks like a bunch of running, equal to each other threads fumbling together all the memory from the inside. And this is despite the fact that part of the threads “as if” refers to one running application, some to another - all this is just in your head, and Inferno before this grouping of threads doesn’t work on applications.

If you were horrified by the idea of ​​not protecting the memory of some applications from others and you remembered DOS ... then I will calm you - this problem, like many others in Inferno, is solved at the architectural level and does not require any special efforts "to protect". Namely - in Dis (virtual machine) there is simply no way for direct memory access to the address, all pointers are essentially high-level links to fixed memory locations. Thus, any thread has access only to those memory areas to which it has pointers. And a pointer to an existing (i.e., allocated by some other thread) thread can receive a thread only by a parameter or via IPC between threads. Thus, strong Dis typing provides absolute memory protection as a “side effect” . :)

Source: https://habr.com/ru/post/8952/


All Articles