In September, "Regular Expressions" described several ways kernel programming has become more manageable: instead of being restricted to a narrow sliver of elite programmers, it's now feasible for nearly anyone who maintains his or her own Linux host.
Much the same has happened with work on device drivers. While authorship of professional-caliber device drivers remains a specialized pursuit, it's now possible to be productive with device drivers recreationally, or at least on a basis other than full-time devotion.
Software for Easier Device Drivers
Most of the changes easing this work are familiar from larger trends in kernel programming mentioned earlier: standards for loadable modules, rationalization of device driver interfaces, the availability of virtual machines for testing, less expensive hardware, and so on. This week, we look at two general techniques that have proven more successful with device drivers than you might realize: programming in userland and with high-level languages.
Traditionally, device drivers have connected deep inside an operating system's kernel. In recent years, progressively better-defined interfaces have narrowed the ties that a device driver must have to a kernel, to the point that now it's even feasible to write device drivers "in userland," that is, without kernel rebinding, just like more normal applications.
FUSD, from the Center for Embedded Networking Sensing (CENS), is the best example of this. "...CENS... is a major research enterprise focused on... applying this revolutionary technology to critical scientific and societal pursuits", according to the profile on its own Web site. "[T]his revolutionary technology" involves miniaturization and networking of sensors, to "foster ... a deeper understanding of the natural and built environments." CENS looks at all sorts of things in the world as opportunities for digital sensing; it's a group whose experience with device drivers is deep.
FUSD, reminiscent in several regards of the FUSE that appeared in our September column, is the technical basis for several of these device drivers. As its manual describes, "FUSD is a Linux framework for proxying device file callbacks into user-space, allowing device files to be implemented by daemons instead of kernel code." Although this limits the performance of device drivers implemented with FUSD, its original co-author Jeremy Elson emphasizes that a user-space device driver has more capabilities than a conventional kernel-level driver, including long-running computations, branching into other device drivers, event-based processing, and retrieval of data from the filesystem.
Most crucially for CENS, development of a device driver costs less. A FUSD device can't crash the host as is all-to-common with a kernel-level driver, "and is generally easier to code and debug, especially for people who are application developers," as the other FUSD co-author, Lewis Girod, wrote us. The CENS team can focus more on the science of, for example, the Acoustic ENSBox, and less on fussing with its enabling software.
FUSD's advantages manifest in several other specific benefits. Girod illustrates,
"An example of what FUSD is good for is a 'GPS driver.' ... [T]he 'GPSd' package ... is a user space daemon that acts as a gateway between a GPS unit connected by RS232 and a sockets protocol. Using FUSD you could implement the same RS232 GPS-reading protocol in user-space, but provide access to the features of the GPS via character devices. The advantage is that these devices are browseable and accessible from the shell, rather than using telnet or other special programs to talk to the socket. Another alternative would be to write the GPS driver in the kernel, but this is difficult because it isn't possible to access the device interface for the serial port from inside the kernel....Since FUSD devices are just device files, you can use the usual Unix permissions to control access.
...Another advantage of FUSD is the ability to customize the semantics of the character device, for example to allow notification of events via
select()and to provide reads aligned along message boundaries without framing. This can simplify client code considerably, relative to stream socket protocols."
The result is that FUSD saved CENS considerable time in connecting a variety of microcontroller boards to Linux hosts.
Our explanation here neglects subtleties involved in getting FUSD's implementation right. Elson emphasized when he wrote us that, as straightforward as the idea of FUSD sounds, rendering it in "industrial-strength code ... free of race conditions" came only after "many revisions". The continuing inspirations during this rework were "Linux's /proc filesystem" as a window to the status of the kernel, and "the QNX operation system," as a model for inter-process communication.
Unexpected Languages for Device Drivers
All this work brings still more benefits to FUSD's users. CENS open-sourced FUSD along with many of its other software assets. Among the small community of users outside CENS, at least a few develop in Java and Python. While a conventional kernel-level device driver essentially must be written in C (or perhaps assembler or C++), a FUSD device driver "can be made to work with anything that has access to the POSIX interface," as Girod observes. All the usual advantages of high-level languages immediately apply to work with device drivers.
Brian Warner accomplished so much with a Python binding, in fact, that he contributed it back to CENS, where it's now maintained in the same CVS tree.
FUSD isn't the only basis for "higher-level" device-driver development, though. Another documented example is Pat Thoyt's tclftd2xx. Future Technology Devices International Ltd. [FTDI] are British "specialists in converting legacy peripherals to Universal Serial Bus (USB)." Even though FTDI has done the hard work of packaging libraries for the hardware it supports, it still requires considerable expertise to make good use of those libraries. Thoyts needed to provide for "a general user [to] update the firmware on a device using the FTDI USB chipset." After a little experimentation, he settled on a graphical user interface (GUI) and API coded mostly in Tcl/Tk. As Thoyts wrote us, "In many ways this is a classic use of extensions in Tcl: I've added just enough [C code in a channel driver] to the Tcl interpreter to permit general use of the device."
With that minimal extension, though, supported FTDI devices are now just as programmable at a high level in Tcl as FTDI made them in C.
Is it worth the effort? Here we run into one of "Regular Expressions'" recurring themes: some of the best development stories can be publicized partially or not at all. Our own practice has yielded enough spectacular successes for scripting interfaces (one in particular was very much like tclftd2xx) to encourage us to write this column. In many specific cases, however, the details and especially measurements on the advantages of high-level programming must remain proprietary. What's certain in the public record is that Thoyts provides an open-source interface free for all of us to study and use for our own benefit.
Summary
The expressiveness and productivity of high-level languages can be available even for work in development of device drivers, generally regarded as one of the most specialized and demanding areas of programming.
Kathryn and Cameron run their own consultancy, Phaseit, Inc., specializing in high-reliability and high-performance applications managed by high-level languages. They write about high-level languages and related topics in their "Regular Expressions" columns.
