Schemix FAQ

  • Why?
    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 end. 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?
    From here.
  • 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.
    • and so is money ;-)
  • 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 Read-Evaluate-Print behaviour.
      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 to user-space.
    • 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)
      or
      (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.