The Flux OSKit: A Substrate for Kernel and Language Research
Ford (Utah), Back (Utah), Bensen (UC Davis), Lepreau (Utah), Lin and Shivers (MIT)
Summary. The OSKit provides ultra-modular, well-documented OS
components that can be used as a substrate for "more interesting" OS
research thereby eliminating the headache of uninteresting, tedious OS
development (boot code, drivers) or interface mismatch of new research
modules over existing OS.
More Detail
Related work. Object-Oriented OSes, extensible kernels (SPIN, Vino,
exokernel), embedded, real-time systems all sometimes provide modularity,
but the optional modules depend upon some base layer. Further, they all
strive to define some set of core functionality and set of policies. OSKit
components obtain both modularity and separability. That is, the
components can be used with no required support code and have been designed
to avoid policies (such as process or concurrency models) to allow the
greatest amount of flexibility.
Separability. Separability is achieved via thin glue layers. In simple
cases, this glue layer takes the form of a library function with trivial default
implementations that the client OS can override when necessary. When multiple
implementations of a service must exist (block I/O interface to different
disk device drivers), separability is achieved by implementing interfaces
similar to Java interfaces. A component can have any number of different interfaces.
For example, because the FreeBSD protocol stack code and the Linux device drivers
assume different buffer APIs, each component exports an interface that the
other can understand. Interfaces are realized as tables of function pointers.
For example, a call to a device driver that implements a block I/O interface
will return a pointer through which the interface methods can be invoked.
Legacy code The OSKit provides an extensive set of drivers by
leveraging well-tested legacy code:
- Linux device drivers
- 4.4BSD-derived FreeBSD network protocol stack.
- NetBSD file system support.
To allow the OSKit to track current versions of legacy code, the code is
wrapped using one of two techniques. Small, relatively static legacy code
is modified in the OSKit and subsequently maintained. Large, relatively dynamic
legacy code is encapsulated using a "thin layer of glue code".
Kernel support library. The client OS need only write a
main()
routine if the default setup is adequate. GDB
serial-line debugging support is also provided.
Expose the implementation. The OSKit's interfaces expose the implementation
of its components in order to provide maximum flexibility. The key is that
the client OS need only utilize the implementation details if necessary; the
details are hidden unless requested.
Novel implemenation techniques. There are many other novel
techniques employed by the OSKit. Some examples:
- minimal C library that minimizes dependencies.
- library structure of legacy code maintained for ease
of version tracking.
- oskit packaged as a package that is easy for the client
to build and link against.
- components can vary in granularity: from single functions
(function libraries) to black boxes (component libraries).
- interfaces are COM compliant.
- a number of techniques are employed to avoid symbol clashing:
preprocessing to modify common symbol names, renaming oskit
structures (
oskit_stat
)
- simple blocking model: process level and interrupt level
- to avoid major rewrites in legacy code that assume a certain
process model, maintain (for example)
current
variable in glue code and update as needed (when blocking code
entered).
- sleep records used for sleep/wakeup; client OS
implements the sleep record.
- BSD glue code uses BSD kernel malloc assumes
- all allocated blocks aligned
- blocks that are an even power-of-two size are allocatd
quickly with no overhead.
- allocator automatically keeps track of sizes
and is implemented unchanged on top of memory allocation facility
client OS provides.