Inferno System Internals
Inferno Breakdown
The Inferno operating system is divided in to four components:
The Inferno kernel handles all the system functionality, which includes drivers, file systems, and memory management. This part of the system can either be implemented natively for the host architecture, or can run on top of operating system, such as Linux
The Dis subsystem allows for platform independent executable programs. These programs can be written in languages such as Limbo.
The Limbo language is a strange variant off of C, and Pascal among others. It is a strongly typed language, and it supports features such as threads and channels.
The Styx protocol is used to access all types of networks. It is used to access files and services across a network, and has the in built function to encrypt data. This and the kernel support the mounting of remote name spaces.
Namespaces
Inferno uses the concept of name spaces as a extended metaphor for the file system. Each device in the file system can either reside locally or is on another machine. If a machine lacks a devices, say for example an audio codec, it can mount a server’s directory to its local file system. Now, each program can create its own name space, where each program sees what it wants to see. Once a directory has been mounted to the local file system, it can be accessed like any other device, after it has been bound.. So now you can listed to this sound file, even though your local machine does not have the native capability to do so.
Once a remote file system has been mounted to the local file system, to use it must be then bound to the local name space. To bind something to the local name space you must execute the following command:
bansod.edm.net$ bind -a '#I' /net
Remember this command from the chapter 1? We know it is used to activate the network services. Well what this command actually does is binds to the local name space the
"I" device, which is the internet protocols, to the /net directory. Now, the "I" devices is implemented locally in the kernel, but it is just as well possible to specify a network path to get the device from. The first part, the -a option tells bind to place the files for the "I" devices after the ones that are currently there under the /net directory. Here is a brief subset of the current kernel devices:Table 2-1. Summary of Devices names
|
Name |
Purpose |
|
I |
Internet protocols, they are used for every TCP/IP communication |
|
U |
The Host Operating System file system |
|
p |
Prog device. This provides a list of running processes, much like /proc in Unix |
|
l |
Ethernet device. For physical Ethernet connections |
|
E |
MPEG device. Used to control playback of MPEG devices |
|
M |
Mount driver. This is used to mount remote file systems |
|
/ |
Root file system. Used for the initial startup of the system. |
Also take note that when you execute a
ls -l command in the second column you can see what device a specific file is on. Look (what is in ellipsis is not needed for the discussion):drwxrwxrwx / 0 aditya aditya ... nvfs
-rwxrwxrwx U 0 Everyone Everyone ... permfix.bat
drwxrwxrwx / 0 aditya aditya ... prog
The first entry set is the list of access control rights, the next it the device the file is on. For example the second file is part of the host file system, and the first is part of the root file system. The next two entries shows the owner and group, respectively, and the last is the name of the file (or directory).
Styx
Any file operations that occur between two computers will rely on Styx. The actually protocol and semantics of Styx are hidden from the end user. Whenever a user opens a file that resides on a server Inferno sends out a Styx message, and then waits for the reply.
The Styx protocol is based on T messages and R messages, standing for transaction and reply, respectively. The T messages are always from the client to the server, which then replied to by the appropriate R message. Since there is a maximum size to any one Styx message, an actual request may be broken down into multiple messages by the kernel.
Networking in Inferno
Like all systems in Inferno, the network is abstracted onto the file system. To activate the network you must bind the IP driver to the file system, as illustrated above. Once it has been bound, it creates files for the supported protocols in the directory it has been bound to. After activating the connection server (lib/cs), a program can make a call by issuing a text based command such as
net.test > /net/cs
where
net.test contains (without quotes) "tcp!localhost!6666"This command is broken down into the following: TCP communication protocol, remote host is localhost (this refers to yourself), port 6666, then send that text to the program in /net/cs. After attempting to communicate with cs, you will get back a device name. Then you can open the device, and you will be given a file handle to the network connection. From there you can access the network data using the handle and device name the Cs returned. There a specific files that you can use to access the network connection you just opened. These are:
Table 2-2. TCP Network files
|
File Name |
Description |
|
listen |
Use this file to accept network connections. This will block the current thread until a connection is received |
|
status |
This file can be used to check protocol specific attributes |
|
local |
The local IP address |
|
remote |
The remote connections IP address |
|
data |
Writing to the data file will send data to the connection, and reading it will read from the connection. Keep in mind that reading does block the thread |
|
ctl |
Used to control the connection, such as closing the connection |
The Dis Virtual Machine
The Dis virtual machine provides for a platform independent target for Limbo programs. When a Limbo program is written and compiled, the output executable can be run on any system that supports Dis. Each Dis program can consist of multiple threads. A thread is simply a sub-program that a program may create, such as using the
spawn() statement in Limbo. This thread runs alongside the rest of the threads and will get a slice (also known as a quanta) of time, and in this time it resumes where it was cut off earlier. Now all the scheduling happens transparently to the program, because the system handles all of it.All of the bytecodes (instructions) are interpreted on the host system. The Limbo language and Dis itself are designed so that the interpretation process occurs quickly. Inferno also supports Just In Time compilers, where the bytecode program is translated into native code, and the native code is run. Since the interpretive stage only occurs once in JIT (the translation) it will run subsequently faster.
Conclusion
Well that’s it for this chapter! Next chapter we’ll begin looking into Limbo the programming language, and write a few basic programs in it. You’ll also learn how to use Inferno’s built in debuggers and compiler.