Runnable Userspace Meta Programs
About (top)
Rump (Runnable Userspace Meta Program) is a mechanism for running kernel code as part of a user program's address space. As opposed to executing system calls for requesting kernel services, rump programs do a library call into the kernel code for equivalent functionality. Kernel functionality provided by rump is simply recompiled into userspace from the kernel sources instead of being rewritten, so services imitate the same services being provided by the kernel.
This approach allows:
- virtualization: every address space has its own instance of state. Furthermore, the functionality does not even need to be equal. For example, multiple different networking stacks optimized for different purposes are possible.
- isolation: rump functionality runs in its own instance in a userspace process. In case of a security vulnerability or a program error, direct damage to the system is limited to the process running the rump kernel.
- easy prototyping and development: kernel code can be developed as a normal userspace application. Once development is finished, the code can simply be complied into the kernel.
The approach does not impose a stance on general kernel architecture. Monolithic operation is still possible where desired for example for performance reasons.
There are two possible operating modes for rump. The conceptual difference is further illustrated in Figure 1, “Two operating modes of rump”.
- In front of the kernel. In this scenario, an application makes explicit calls to rump to request services. In principle, kernel functionality is used like with any other programming library.
- Behind the kernel. In this scenerio, rump is used more in a server capacity to provide services normally run in kernelspace. It is invisible to regular applications and they cannot tell the difference between regular kernel and rump operation. An example is file servers using kernel file system code.
The components currently included in rump are:
All functionality is available in the base system as userspace libraries. For a closer explanation of what functionality is provided by each library, see the chapters on the respective functionality.
Kernel code namepace is designated by providing the _KERNEL preprocessor macro for a module during compilation. Kernel interfaces are not exported to userspace programs except indirectly through system calls. Due to these namespace issues it is not possible to call kernel interfaces directly as function calls from userspace programs.
To address the issue, rump provides some kernel interfaces under
an alternate namespace for userspace programs. For example,
vnode operations are provided under the name
RUMP_VOP_OPER() instead of the regular kernel
name VOP_OPER(). However, this is not
a final solution and reworking the interface definitions for
the entire system would be desireable as a future undertaking.
Additionally, rump provides some interfaces for examining
types which are opaque to userspace.
Core Components (top)
The core of rump consists of two libraries:
librump and librumpuser.
The former provides a core necessary to all code running in the
kernel. Examples of this core functionality include memory
allocation and synchronization primitives. Meanwhile, rumpuser
provides a way for code running in kernel space to make system and
library calls to the host system. These are used to implement
various kernel interfaces in librump. For instance, librump does not
itself implement threading and synchronization, but rather uses
the host system pthread implementation and merely does interface
mapping. Similarly, librump uses the host platform
read() and write() system
calls to perform mass media access.
One way to access rump services from an application is to use
rump system calls. They provide equivalent functionality to
real system calls. However, instead of trapping into the
kernel, rump system calls provide interface wrappers which make
normal function calls to the kernel routines inside of rump.
Therefore, the state which they access is not that of the host
kernel, but rather that of the faux kernel active in the calling
process itself. All rump system calls are provided in the
namespace rump_sys. Also, the implicit errno
"parameter" of all system calls is explicitly required as the
last parameter for rump system calls.
For instance, if a rump application wished to adjust the receive
timeout option of a socket it has created, it would issue the call
rump_sys_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv,
sizeof(tv), &rumperrno);
instead of calling the normal interface
setsockopt(), as this call would be handled
by the host kernel running the rump process.
The system calls provided by rump are listed in the header
<rump/rump_syscalls.h>.
File Systems (top)
File systems are in essence protocol translators being able to transform the virtual file system protocol into the physical file system protocol. This might be for example disk layout in the case of FFS or a networking protocol in the case of NFS. As this functionality rarely fully available in userspace, this opens up new possibilities for applications. Even if it is already available, the rump solution allows for code reuse without the need for reimplementation.
Currently the following NetBSD kernel file systems are available as rump libraries:
- cd9660fs, efs, ext2fs, ffs, hfs, lfs, nfs, msdosfs, nfs, ntfs, puffs, tmpfs, and udf
Rump file systems are supported both in front of the kernel and behind the kernel (follow the links for further information):
- In Front: Process Local File Servers
- Behind: Kernel File Systems as Userspace Servers
Networking (top)
Rump provides networking stack support either for in-kernel consumers wishing to networking services or for specifically written user programs wishing to use the kernel networking stack for purposes of virtualization and development.
There are two different modes of operation: full userspace networking stack or host kernel networking stack. The the first case the entire networking stack is run in userspace and is interfaced with the physical network through a tap device. In the latter case, only the kernel sockets layer is run in userspace. A virtual protocol family provides networking access using socket system calls on the host system. The tradeoff between the two is essentially a question of purpose: the latter does not require any interface configuration priviledges and uses the same network address as all other applications on the host. It is useful when using kernel components which just require access to the networking on the abstract sockets layer.
For an example of how to use rump networking, please see the network test program It is a simple program which connects to www.NetBSD.org, reads index.html, and dumps it on screen. The program shows how to configure a virtual interface and routing and how to open a rump networking socket and how to send and receive data through it.
Futher Information (top)
You can browse the source code history online. See
README.dirs in the top level directory for
information on what to find where.
The rump manual page provides further programming information: rump(3).
![[NetBSD Logo]](../../images/NetBSD-headerlogo.png)


