The intended uses of Schemix are those where you require quick,
interactive access to the kernel's internals. For example, you might want
a new kernel interface that looks like the ones you find in /proc.
You could write this interface in C. Suppose though, that you want to
invest very little time in writing the interface, compiling it and getting
it up and running. Suppose further, that you haven't quite decided on
the format in which you want the interface to present its information to
the outside world, so you'd like to try several different versions before
you stick with one. Suppose you don't want to reboot to get the interface
running. Suppose you only want the interface to exist for a few minutes
and then to go away when you are finished using it. That's one thing you
might use Schemix for.
- So why Scheme?
Scheme is a very safe language. It doesn't allow you to create arbitrary
pointers or over-run buffers. If you divide by zero, the universe will not
This makes it a good language for prototyping, because prototyping
is basically the act of making lots of mistakes until, eventually,
you make the right mistake and call it a finished product.
- Where can I get it?
- How can I contribute?
- Bug reports (to the mailing list) are always welcome.
- As are donations of computers with non-x86 architectures to test Schemix on.
Can I have developer CVS access?
Most likely, yes. I am always happy to find developers who want to work on
Schemix. I would ask that you subscribe to schemix-devel for a while
before you ask for CVS access though.
How does Schemix work?
Schemix is implemented entirely in kernel space. It implements an arbitrary
number of Scheme interpreters, each one separate from the others, and each
one attached to some device in the /dev hierarchy.
There are a few major parts to Schemix that require individual explanation:
- Each Scheme interpreter is structured as in TinyScheme. This part of
the code is quite easy to understand.
- When the DevFS system is not enabled there is just one Scheme
interpreter, which is attached to /dev/schemix. However, when DevFS
is enabled, an arbitrary number of Scheme interpreters can be attached
to devices in /dev.
- When a user-space program (e.g. cat, or an Emacs session) writes something
to a Schemix device, the kernel calls a hook function in the Schemix code,
telling it which device was written to. Schemix figures out which Scheme
interpreter is attached to that device and passes whatever was written to
the apropriate code. If that code causes output to be written, that output
is buffered until a user-space program reads from the device.
- When a user-space program reads from a Schemix device Schemix looks to
see if there is anything in that device's output buffer and, if there is,
passes the buffer contents to the user-space program
- The above two points are slightly complicated by the *on-read* and
*on-write* hooks. These can be defined for each Scheme interpreter and
are used to customise the interface to the device. The *on-write* hook
takes one argument, a string, which is whatever was written to the device.
If the *on-write* hook is defined then it bypasses the usual
When the *on-read* hook is defined, it is called every time a user-space
program tries to read from the device. The *on-read* hook should take no
arguments. If it returns #f, the buffer contents (if any) are not passed
- If the kallsyms patch is present and Schemix was compiled with it
enabled then a module::name syntax is available.
When the reader encounters a symbol of the form module::name, it uses
kallsyms calls to look for a symbol called "name" which is in a module
called "module". The kernel is treated as a special module, called "kernel".
You can't make use of these special symbols until you have told Schemix
what their type is, using assert-type. For example you can do:
(assert-type 'int kernel::nr_threads)
(assert-type '(char 4) kernel::nr_threads)
The second form tells Schemix to consider kernel::nr_threads as an array
of bytes rather than an integer. You can use array-ref and array-set! to
manipulate arrays defined in this way (see SRFI 25 for details).
- Again, if the kallsyms patch is installed and enabled, you can make
calls to kernel functions. Currently you can only call a small subset of
all kernel functions though.
I want to use a kernel function in Schemix that is currently not supported.
What should I do?
If you want to use the function right now, I suggest you write a little
wrapper around it (add an opcode to schemix-opcodes.h and a case statement
for that opcode in schemix.c). This is quite an easy thing to do for a
handful of functions. However, don't expect me to accept a patch
for the wrapper as this isn't the way I want to do things long term.
The long term way this needs to be done is that Schemix gets told by the
user "function foo::bar takes the following arguments and returns the following
value". Schemix should then figure out the function linkage (perhaps using
libffi) and be able to call the function without any wrapper.
Actually, before we get to this stage, Schemix needs good support for C
structures (since they will be used as arguments and return values of several
functions). This is what I'm working on at the moment.