HTML "The Use of Name Spaces in Plan 9
TL
The Use of Name Spaces in Plan 9
AU
Rob Pike
Dave Presotto
Ken Thompson
Howard Trickey
Phil Winterbottom
AI
MH
USA
AB
FS
Appeared in
I
Operating Systems Review,
R
Vol. 27, #2, April 1993, pp. 72-76
(reprinted from
I
Proceedings of the 5th ACM SIGOPS European Workshop,
R
Mont Saint-Michel, 1992, Paper nº 34).
FE
Plan 9 is a distributed system built at the Computing Sciences Research
Center of AT&T Bell Laboratories (now Lucent Technologies, Bell Labs) over the last few years.
Its goal is to provide a production-quality system for software
development and general computation using heterogeneous hardware
and minimal software.  A Plan 9 system comprises CPU and file
servers in a central location connected together by fast networks.
Slower networks fan out to workstation-class machines that serve as
user terminals.  Plan 9 argues that given a few carefully
implemented abstractions
it is possible to
produce a small operating system that provides support for the largest systems
on a variety of architectures and networks. The foundations of the system are
built on two ideas: a per-process name space and a simple message-oriented
file system protocol.
AE
PP
The operating system for the CPU servers and terminals is
structured as a traditional kernel: a single compiled image
containing code for resource management, process control,
user processes,
virtual memory, and I/O.  Because the file server is a separate
machine, the file system is not compiled in, although the management
of the name space, a per-process attribute, is.
The entire kernel for the multiprocessor SGI Power Series machine
is 25000 lines of C,
the largest part of which is code for four networks including the
Ethernet with the Internet protocol suite.
Fewer than 1500 lines are machine-specific, and a
functional kernel with minimal I/O can be put together from
source files totaling 6000 lines. [Pike90]
PP
The system is relatively small for several reasons.
First, it is all new: it has not had time to accrete as many fixes
and features as other systems.
Also, other than the network protocol, it adheres to no
external interface; in particular, it is not Unix-compatible.
Economy stems from careful selection of services and interfaces.
Finally, wherever possible the system is built around
two simple ideas:
every resource in the system, either local or remote,
is represented by a hierarchical file system; and
a user or process
assembles a private view of the system by constructing a file
I
name space
R
that connects these resources. [Needham]
SH
File Protocol
PP
All resources in Plan 9 look like file systems.
That does not mean that they are repositories for
permanent files on disk, but that the interface to them
is file-oriented: finding files (resources) in a hierarchical
name tree, attaching to them by name, and accessing their contents
by read and write calls.
There are dozens of file system types in Plan 9, but only a few
represent traditional files.
At this level of abstraction, files in Plan 9 are similar
to objects, except that files are already provided with naming,
access, and protection methods that must be created afresh for
objects.  Object-oriented readers may approach the rest of this
paper as a study in how to make objects look like files.
PP
The interface to file systems is defined by a protocol, called 9P,
analogous but not very similar to the NFS protocol.
The protocol talks about files, not blocks; given a connection to the root
directory of a file server,
the 9P messages navigate the file hierarchy, open files for I/O,
and read or write arbitrary bytes in the files.
9P contains 17 message types: three for
initializing and
authenticating a connection and fourteen for manipulating objects.
The messages are generated by the kernel in response to user- or
kernel-level I/O requests.
Here is a quick tour of the major message types.
The
CW auth
and
CW attach
messages authenticate a connection, established by means outside 9P,
and validate its user.
The result is an authenticated
I channel
that points to the root of the
server.
The
CW clone
message makes a new channel identical to an existing channel,
which may be moved to a file on the server using a
CW walk
message to descend each level in the hierarchy.
The
CW stat
and
CW wstat
messages read and write the attributes of the file pointed to by a channel.
The
CW open
message prepares a channel for subsequent
CW read
and
CW write
messages to access the contents of the file, while
CW create
and
CW remove
perform, on the files, the actions implied by their names.
The
CW clunk
message discards a channel without affecting the file.
None of the 9P messages consider caching; file caches are provided,
when needed, either within the server (centralized caching)
or by implementing the cache as a transparent file system between the
client and the 9P connection to the server (client caching).
PP
For efficiency, the connection to local
kernel-resident file systems, misleadingly called
I devices,
is by regular rather than remote procedure calls.
The procedures map one-to-one with 9P message  types.
Locally each channel has an associated data structure
that holds a type field used to index
a table of procedure calls, one set per file system type,
analogous to selecting the method set for an object.
One kernel-resident file system, the
I
mount device,
R
translates the local 9P procedure calls into RPC messages to
remote services over a separately provided transport protocol
such as TCP or IL, a new reliable datagram protocol, or over a pipe to
a user process.
Write and read calls transmit the messages over the transport layer.
The mount device is the sole bridge between the procedural
interface seen by user programs and remote and user-level services.
It does all associated marshaling, buffer
management, and multiplexing and is
the only integral RPC mechanism in Plan 9.
The mount device is in effect a proxy object.
There is no RPC stub compiler; instead the mount driver and
all servers just share a library that packs and unpacks 9P messages.
SH
Examples
PP
One file system type serves
permanent files from the main file server,
a stand-alone multiprocessor system with a
350-gigabyte
optical WORM jukebox that holds the data, fronted by a two-level
block cache comprising 7 gigabytes of
magnetic disk and 128 megabytes of RAM.
Clients connect to the file server using any of a variety of
networks and protocols and access files using 9P.
The file server runs a distinct operating system and has no
support for user processes; other than a restricted set of commands
available on the console, all it does is answer 9P messages from clients.
PP
Once a day, at 5:00 AM,
the file server sweeps through the cache blocks and marks dirty blocks
copy-on-write.
It creates a copy of the root directory
and labels it with the current date, for example
CW 1995/0314 .
It then starts a background process to copy the dirty blocks to the WORM.
The result is that the server retains an image of the file system as it was
early each morning.
The set of old root directories is accessible using 9P, so a client
may examine backup files using ordinary commands.
Several advantages stem from having the backup service implemented
as a plain file system.
Most obviously, ordinary commands can access them.
For example, to see when a bug was fixed
P1
grep 'mouse bug fix' 1995/*/sys/src/cmd/8½/file.c
P2
The owner, access times, permissions, and other properties of the
files are also backed up.
Because it is a file system, the backup
still has protections;
it is not possible to subvert security by looking at the backup.
PP
The file server is only one type of file system.
A number of unusual services are provided within the kernel as
local file systems.
These services are not limited to I/O devices such
as disks.  They include network devices and their associated protocols,
the bitmap display and mouse,
a representation of processes similar to
CW /proc
[Killian], the name/value pairs that form the `environment'
passed to a new process, profiling services,
and other resources.
Each of these is represented as a file system \(em
directories containing sets of files \(em
but the constituent files do not represent permanent storage on disk.
Instead, they are closer in properties to UNIX device files.
PP
For example, the
I console
device contains the file
CW /dev/cons ,
similar to the UNIX file
CW /dev/console :
when written,
CW /dev/cons
appends to the console typescript; when read,
it returns characters typed on the keyboard.
Other files in the console device include
CW /dev/time ,
the number of seconds since the epoch,
CW /dev/cputime ,
the computation time used by the process reading the device,
CW /dev/pid ,
the process id of the process reading the device, and
CW /dev/user ,
the login name of the user accessing the device.
All these files contain text, not binary numbers,
so their use is free of byte-order problems.
Their contents are synthesized on demand when read; when written,
they cause modifications to kernel data structures.
PP
The
I process
device contains one directory per live local process, named by its numeric
process id:
CW /proc/1 ,
CW /proc/2 ,
etc.
Each directory contains a set of files that access the process.
For example, in each directory the file
CW mem
is an image of the virtual memory of the process that may be read or
written for debugging.
The
CW text
file is a sort of link to the file from which the process was executed;
it may be opened to read the symbol tables for the process.
The
CW ctl
file may be written textual messages such as
CW stop
or
CW kill
to control the execution of the process.
The
CW status
file contains a fixed-format line of text containing information about
the process: its name, owner, state, and so on.
Text strings written to the
CW note
file are delivered to the process as
I notes,
analogous to UNIX signals.
By providing these services as textual I/O on files rather
than as system calls (such as
CW kill )
or special-purpose operations (such as
CW ptrace ),
the Plan 9 process device simplifies the implementation of
debuggers and related programs.
For example, the command
P1
cat /proc/*/status
P2
is a crude form of the
CW ps
command; the actual
CW ps
merely reformats the data so obtained.
PP
The
I bitmap
device contains three files,
CW /dev/mouse ,
CW /dev/screen ,
and
CW /dev/bitblt ,
that provide an interface to the local bitmap display (if any) and pointing device.
The
CW mouse
file returns a fixed-format record containing
1 byte of button state and 4 bytes each of
I x
and
I y
position of the mouse.
If the mouse has not moved since the file was last read, a subsequent read will
block.
The
CW screen
file contains a memory image of the contents of the display;
the
CW bitblt
file provides a procedural interface.
Calls to the graphics library are translated into messages that are written
to the
CW bitblt
file to perform bitmap graphics operations.  (This is essentially a nested
RPC protocol.)
PP
The various services being used by a process are gathered together into the
process's
I
name space,
R
a single rooted hierarchy of file names.
When a process forks, the child process shares the name space with the parent.
Several system calls manipulate name spaces.
Given a file descriptor
CW fd
that holds an open communications channel to a service,
the call
P1
mount(int fd, char *old, int flags)
P2
authenticates the user and attaches the file tree of the service to
the directory named by
CW old .
The
CW flags
specify how the tree is to be attached to
CW old :
replacing the current contents or appearing before or after the
current contents of the directory.
A directory with several services mounted is called a
I union
directory and is searched in the specified order.
The call
P1
bind(char *new, char *old, int flags)
P2
takes the portion of the existing name space visible at
CW new ,
either a file or a directory, and makes it also visible at
CW old .
For example,
P1
bind("1995/0301/sys/include", "/sys/include", REPLACE)
P2
causes the directory of include files to be overlaid with its
contents from the dump on March first.
PP
A process is created by the
CW rfork
system call, which takes as argument a bit vector defining which
attributes of the process are to be shared between parent
and child instead of copied.
One of the attributes is the name space: when shared, changes
made by either process are visible in the other; when copied,
changes are independent.
PP
Although there is no global name space,
for a process to function sensibly the local name spaces must adhere
to global conventions.
Nonetheless, the use of local name spaces is critical to the system.
Both these ideas are illustrated by the use of the name space to
handle heterogeneity.
The binaries for a given architecture are contained in a directory
named by the architecture, for example
CW /mips/bin ;
in use, that directory is bound to the conventional location
CW /bin .
Programs such as shell scripts need not know the CPU type they are
executing on to find binaries to run.
A directory of private binaries
is usually unioned with
CW /bin .
(Compare this to the
I
ad hoc
R
and special-purpose idea of the
CW PATH
variable, which is not used in the Plan 9 shell.)
Local bindings are also helpful for debugging, for example by binding
an old library to the standard place and linking a program to see
if recent changes to the library are responsible for a bug in the program.
PP
The window system,
CW 8½
[Pike91], is a server for files such as
CW /dev/cons
and
CW /dev/bitblt .
Each client sees a distinct copy of these files in its local
name space: there are many instances of
CW /dev/cons ,
each served by
CW 8½
to the local name space of a window.
Again,
CW 8½
implements services using
local name spaces plus the use
of I/O to conventionally named files.
Each client just connects its standard input, output, and error files
to
CW /dev/cons ,
with analogous operations to access bitmap graphics.
Compare this to the implementation of
CW /dev/tty
on UNIX, which is done by special code in the kernel
that overloads the file, when opened,
with the standard input or output of the process.
Special arrangement must be made by a UNIX window system for
CW /dev/tty
to behave as expected;
CW 8½
instead uses the provision of the corresponding file as its
central idea, which to succeed depends critically on local name spaces.
PP
The environment
CW 8½
provides its clients is exactly the environment under which it is implemented:
a conventional set of files in
CW /dev .
This permits the window system to be run recursively in one of its own
windows, which is handy for debugging.
It also means that if the files are exported to another machine,
as described below, the window system or client applications may be
run transparently on remote machines, even ones without graphics hardware.
This mechanism is used for Plan 9's implementation of the X window
system: X is run as a client of
CW 8½ ,
often on a remote machine with lots of memory.
In this configuration, using Ethernet to connect
MIPS machines, we measure only a 10% degradation in graphics
performance relative to running X on
a bare Plan 9 machine.
PP
An unusual application of these ideas is a statistics-gathering
file system implemented by a command called
CW iostats .
The command encapsulates a process in a local name space, monitoring 9P
requests from the process to the outside world \(em the name space in which
CW iostats
is itself running.  When the command completes,
CW iostats
reports usage and performance figures for file activity.
For example
P1
iostats 8½
P2
can be used to discover how much I/O the window system
does to the bitmap device, font files, and so on.
PP
The
CW import
command connects a piece of name space from a remote system
to the local name space.
Its implementation is to dial the remote machine and start
a process there that serves the remote name space using 9P.
It then calls
CW mount
to attach the connection to the name space and finally dies;
the remote process continues to serve the files.
One use is to access devices not available
locally.  For example, to write a floppy one may say
P1
import lab.pc /a: /n/dos
cp foo /n/dos/bar
P2
The call to
CW import
connects the file tree from
CW /a:
on the machine
CW lab.pc
(which must support 9P) to the local directory
CW /n/dos .
Then the file
CW foo
can be written to the floppy just by copying it across.
PP
Another application is remote debugging:
P1
import helix /proc
P2
makes the process file system on machine
CW helix
available locally; commands such as
CW ps
then see
CW helix 's
processes instead of the local ones.
The debugger may then look at a remote process:
P1
db /proc/27/text /proc/27/mem
P2
allows breakpoint debugging of the remote process.
Since
CW db
infers the CPU type of the process from the executable header on
the text file, it supports
cross-architecture debugging, too.
Care is taken within
CW db
to handle issues of byte order and floating point; it is possible to
breakpoint debug a big-endian MIPS process from a little-endian i386.
PP
Network interfaces are also implemented as file systems [Presotto].
For example,
CW /net/tcp
is a directory somewhat like
CW /proc :
it contains a set of numbered directories, one per connection,
each of which contains files to control and communicate on the connection.
A process allocates a new connection by accessing
CW /net/tcp/clone ,
which evaluates to the directory of an unused connection.
To make a call, the process writes a textual message such as
CW 'connect
CW 135.104.53.2!512'
to the
CW ctl
file and then reads and writes the
CW data
file.
An
CW rlogin
service can be implemented in a few of lines of shell code.
PP
This structure makes network gatewaying easy to provide.
We have machines with Datakit interfaces but no Internet interface.
On such a machine one may type
P1
import helix /net
telnet tcp!ai.mit.edu
P2
The
CW import
uses Datakit to pull in the TCP interface from
CW helix ,
which can then be used directly; the
CW tcp!
notation is necessary because we routinely use multiple networks
and protocols on Plan 9\(emit identifies the network in which
CW ai.mit.edu
is a valid name.
PP
In practice we do not use
CW rlogin
or
CW telnet
between Plan 9 machines.  Instead a command called
CW cpu
in effect replaces the CPU in a window with that
on another machine, typically a fast multiprocessor CPU server.
The implementation is to recreate the
name space on the remote machine, using the equivalent of
CW import
to connect pieces of the terminal's name space to that of
the process (shell) on the CPU server, making the terminal
a file server for the CPU.
CPU-local devices such as fast file system connections
are still local; only terminal-resident devices are
imported.
The result is unlike UNIX
CW rlogin ,
which moves into a distinct name space on the remote machine,
or file sharing with
CW NFS ,
which keeps the name space the same but forces processes to execute
locally.
Bindings in
CW /bin
may change because of a change in CPU architecture, and
the networks involved may be different because of differing hardware,
but the effect feels like simply speeding up the processor in the
current name space.
SH
Position
PP
These examples illustrate how the ideas of representing resources
as file systems and per-process name spaces can be used to solve
problems often left to more exotic mechanisms.
Nonetheless there are some operations in Plan 9 that are not
mapped into file I/O.
An example is process creation.
We could imagine a message to a control file in
CW /proc
that creates a process, but the details of
constructing the environment of the new process \(em its open files,
name space, memory image, etc. \(em are too intricate to
be described easily in a simple I/O operation.
Therefore new processes on Plan 9 are created by fairly conventional
CW rfork
and
CW exec
system calls;
CW /proc
is used only to represent and control existing processes.
PP
Plan 9 does not attempt to map network name spaces into the file
system name space, for several reasons.
The different addressing rules for various networks and protocols
cannot be mapped uniformly into a hierarchical file name space.
Even if they could be,
the various mechanisms to authenticate,
select a service,
and control the connection would not map consistently into
operations on a file.
PP
Shared memory is another resource not adequately represented by a
file name space.
Plan 9 takes care to provide mechanisms
to allow groups of local processes to share and map memory.
Memory is controlled
by system calls rather than special files, however,
since a representation in the file system would imply that memory could
be imported from remote machines.
PP
Despite these limitations, file systems and name spaces offer an effective
model around which to build a distributed system.
Used well, they can provide a uniform, familiar, transparent
interface to a diverse set of distributed resources.
They carry well-understood properties of access, protection,
and naming.
The integration of devices into the hierarchical file system
was the best idea in UNIX.
Plan 9 pushes the concepts much further and shows that
file systems, when used inventively, have plenty of scope
for productive research.
SH
References
LP
[Killian] T. Killian, ``Processes as Files'', USENIX Summer Conf. Proc., Salt Lake City, 1984
br
[Needham] R. Needham, ``Names'', in
I
Distributed systems,
R
S. Mullender, ed.,
Addison Wesley, 1989
br
[Pike90] R. Pike, D. Presotto, K. Thompson, H. Trickey,
``Plan 9 from Bell Labs'',
UKUUG Proc. of the Summer 1990 Conf.,
London, England,
1990
br
[Presotto] D. Presotto, ``Multiprocessor Streams for Plan 9'',
UKUUG Proc. of the Summer 1990 Conf.,
London, England,
1990
br
[Pike91] Pike, R., ``8.5, The Plan 9 Window System'', USENIX Summer
Conf. Proc., Nashville, 1991