Author Contact Information and Acknowledgments

FUSD was written by Jeremy Elson (jelson@circlemud.org)
and Lewis Girod, originally at Sensoria Corporation. The public
fork is now maintained by those authors from the University of
California, Los Angeles. If you have bug reports, patches, suggestions,
or any other comments, please feel free to contact the authors.

FUSD has two SourceForge-host
mailing lists: a low-traffic list for announcements
(fusd-announce) and a list for general discussion
(fusd-devel). Subscription information for both lists is
available at the SourceForge's FUSD
mailing list page.

What is FUSD?

FUSD (pronounced fused) is a Linux framework for proxying
device file callbacks into user-space, allowing device files to be
implemented by daemons instead of kernel code. Despite being
implemented in user-space, FUSD devices can look and act just like any
other file under /dev which is implemented by kernel callbacks.

A user-space device driver can do many of the things that kernel
drivers can't, such as perform a long-running computation, block while
waiting for an event, or read files from the file system. Unlike
kernel drivers, a user-space device driver can use other device
drivers--that is, access the network, talk to a serial port, get
interactive input from the user, pop up GUI windows, or read from
disks. User-space drivers implemented using FUSD can be much easier
to debug; it is impossible for them to crash the machine, are easily
traceable using tools such as gdb, and can be killed and
restarted without rebooting even if they become corrupted. FUSD
drivers don't have to be in C--Perl, Python, or any other language
that knows how to read from and write to a file descriptor can work
with FUSD. User-space drivers can be swapped out, whereas kernel
drivers lock physical memory.

FUSD drivers are conceptually similar to kernel drivers: a set of
callback functions called in response to system calls made on file
descriptors by user programs. FUSD's C library provides a device
registration function, similar to the kernel's
devfs_register_chrdev() function, to create new devices.
fusd_register() accepts the device na me and a structure full
of pointers. Those pointers are callback functions which are called
in response to certain user system calls--for example, when a process
tries to open, close, read from, or write to the device file. The
callback functions should conform to the standard definitions of POSIX
system call behavior. In many ways, the user-space FUSD callback
functions are identical to their kernel counterparts.

The proxying of kernel system calls that makes this kind of program
possible is implemented by FUSD, using a combination of a kernel
module and cooperating user-space library. The kernel module
implements a character device, /dev/fusd, which is used as a
control channel between the two. fusd_register() uses this channel
to send a message to the FUSD kernel module, telling the name of the
device the user wants to register. The kernel module, in turn,
registers that device with the kernel proper using devfs. devfs and
the kernel don't know anything unusual is happening; it appears from
their point of view that the registered devices are simply being
implemented by the FUSD module.

Later, when kernel makes a callback due to a system call (e.g. when
the character device file is opened or read), the FUSD kernel module's
callback blocks the calling process, marshals the arguments of the
callback into a message and sends it to user-space. Once there, the
library half of FUSD unmarshals it and calls whatever user-space
callback the FUSD driver passed to fusd_register(). When that
user-space callback returns a value, the process happens in reverse:
the return value and its side-effects are marshaled by the library
and sent to the kernel. The FUSD kernel module unmarshals this
message, matches it up with a corresponding outstanding request, and
completes the system call. The calling process is completely unaware
of this trickery; it simply enters the kernel once, blocks, unblocks,
and returns from the system call--just as it would for any other
blocking call.

One of the primary design goals of FUSD is stability. It
should not be possible for a FUSD driver to corrupt or crash the
kernel, either due to error or malice. Of course, like any other
program a buggy driver may corrupt itself (e.g., due to a buffer
overrun). However, strict error checking is implemented at the
user-kernel boundary which prevents drivers from corrupting the
kernel or any other user-space process--including the errant driver's
own clients, and other FUSD drivers.

For a more detailed description of what FUSD is, and how to use it,
please take a look at the comprehensive FUSD User's
Manual.

Related Work

UserFS, a Linux
framework that allows user processes to be mounted as a normal
filesystem by Jeremy Fitzhardinge