After reading the previous parts, a question should arise in your head: how to get a port (a send right) to a server ? Say, how to get a send right to the TCP/IP stack ? The commonly used method is a naming service: a special server, on which you can get a port right in exchange from a name (like port = ns_get_port (ns, "pfinet"); to get a port to the TCP/IP stack). The port to the naming service can be given a creation time. But this has several problems:
The idea of the Hurd consists in using the whole VFS (virtual filesystem) as the naming service. Every node in the filesystem is in fact an access point to an underlying server, called a translator.
The function ``file_name_lookup'' of the C library does a recursive lookup of the specified name, and then gives a send right to the translator listening (if allowed by the node permissions). For example, if you have a /home partition and you do a request for ``/home/kilobug/plop'', the file_name_lookup will ask for /home/kilobug/plop to the root translator (known by every application), which will anwser with ``well, I don't know this, but you can ask for kilobug/plop to that server'', and join a send right to the server handling the filesystem of /home. Then, file_name_lookup will ask for kilobug/plop to this send right, and will get a send right corresponding to this file. RPCs like io_read or io_write can then be done.
If you ask for /servers/socket/pfinet you'll get a port right to the TCP/IP translator, and you'll be able to do RPC to open sockets, or send a ``ping'' request.
The VFS also provides the permission mechanism, through standard Unix permissions.
A translator is a normal program, running in its own address space, with the rights and the identity of the user who started it. It is not a privileged process (even if many of them, like the system-wide TCP/IP stack, were started by the system administrator during the boot process, any user can run a translator).
A translator is usually a highly multi-threaded program, which can answer to different, even simultaneous, RPCs. The RPCs can be related to file handling (like io_* or dir_*), but can be completely unrelated if needed, like the proc_* RPC family of the proc server (the server handling Unix-like processes, processes groups, signals, ...)
The most common translator example is the ftpfs translator; you can see a case of use in the figure 6.3.1.
Another example, showing what can be done by using the filesystem as the naming service, is the ``crash'' translator. The ``crash'' translator is invoked when a program performs a fatal error (like a segmentation fault). On the Hurd, there are three available crash servers: one which just freezes the process in memory, one which kills the process, and a last one which kills the the process and drop a core file. The ``/server/crash'' file is in fact a symlink to the selected crash server. Switching to another crash server can be done just by changing the link target to point to the node where the crash server you want to use lives. symlink - which is also a translator - redirects RPCs done to ``/server/crash'' to, for example ``/server/crash-suspend'' which does the expected job.