The Best Without X

Small computers, especially those with little memory, don't run the X Window System---or any other graphic environment---very smoothly. An intelligent keyboard configuration and use of the gpm mouse server will help you exploit your small Linux box to its fullest.

by Alessandro Rubini

If your system doesn't run X-Windows, you may miss the mouse support that makes interactive programs so easy to use. gpm, the general purpose mouse server, is designed with you in mind. Instead of having a multitude of mouse drivers, several from each mouse vendor, some that work well, others that don't, you can run gpm, which can talk to all mice, and works quite well. This article explains how to set up gpm to work with your mouse and programs, and also explains how to set up your text console to work the best for you.

The gpm program is derived from the older selection program, which was solely for cut-and-paste on the Linux console. gpm acts like selection until a client requests mouse events. Because gpm manages each console as an independent entity, you can use your multi-console text screen like a multi-window graphic environment. This article refers to gpm-1.0.

Configuring the Mouse Device

One major problem with Linux is hardware compatibility, and the mouse is no exception. Companies are always releasing new mice, and each of them provides a different mouse driver for DOS. Linux users are left alone with their device and no driver. Fortunately, companies tend to converge on a few ``standard'' protocols, which are supported by both XFree86 and gpm. Moreover, the gpm package includes gpm-test, which can help in detecting your own mouse port and protocol, and which suggests which command-line options you should use to invoke the daemon.

You must provide the protocol name and options to gpm on the command line, together with your own preferences. These will affect all mouse response until the server dies. One preference allows button reordering: left-handed people can reorder the buttons by using the command line option -B 321, and owners of two-button devices can use -B 132 to use the right button as if it were the middle one, a useful way to paste the cut-buffer in Emacs without modifying Emacs itself. The current version of the gpm server duplicates the functionality of both mconv2 and MultiMouse, and can act as a ``repeater''. You can merge the events from two different devices and pass them along to the X server. This is useful if you use a laptop with both an internal pointer and an external mouse. If you'd like to use one mouse in each hand but keep the internal trackball active, however, gpm can't help you---no more than two mouse devices can be read at a time.

The ``repeater'' option is automatically enabled if you read two mice, but can be triggered independently; if you use gpm as a repeater, the X server can be configured to read /dev/gpmdata, a fifo named pipe, where gpm puts mouse packets received while the console is in graphic mode. This option is meant to be used by owners of busmice who want to multiplex text-only and X operation without killing and restarting the daemon. Owners of new dual-mode mice, which run the three-button protocol only if the middle button is kept down at mouse initialization, will enjoy it as well, because the device is initialized only at boot time.

How Does gpm Work?

The core of the gpm daemon is currently built around the select()system call and the process runs in the user space of the systems memory. The main loop of the daemon listens to a Unix-domain socket and to the mouse, and uses them in conjunction to multiplex event retrieval and management of new clients. The main loop of gpm can be (and has been) used to build a concurrent daemon for network services by modifying just a few details.

The choice of a user-space server for the mouse was originally meant to help owners of low-end boxes---the process could be swapped out when not in use and thus save a little precious memory. Unfortunately, when you use Emacs, a perceptible delay in delivery of mouse events can severely degrade performance, and combined use of mouse and keyboard is completely unreasonable on a slightly loaded machine.

The swap-in delay can be removed by locking the process in memory, but in the case of Emacs two processes should be locked in memory. The goal for gpm-2.0, which will supersede the current version, is to provide the choice between a user process and a kernel module. The advantage of running a kernel module is mainly fewer context-switches (and no swap-in delay whatsoever), while the main disadvantage is the waste of memory. The module alternative will offer the same interface to client applications, but will use a device node instead of a socket.

Configuring the Keyboard

The Linux keyboard is fully customizable (could you doubt it?) and can be tailored for smart text-only usage. The idea is to reduce context-switch time to get more performance out of your multitasking brain. This is the basic idea behind virtual consoles.

Here are some suggestions for improving your keyboard. I will describe some of the useful changes to make, and then give the appropriate lines for the loadkeys program to effect the change.

The modifications listed above work with my keyboard. Check your actual keycodes using showkeys before applying these changes. showkeys is part of the kbd package. If you're a real typist, you can make something really useful out of the twelve function keys. Read the keytables(5) man page to probe further. For more information on how to modify the keyboard, see Kernel Korner in Linux Journal #14.

Spawning New Consoles

``Why should I use the numeric keypad to switch between 15 consoles when I only have 6?'' I hear you say. Linux can handle a s many as 63 virtual console, and 6 (or whatever else) is only the number of ``login prompts'' configured in your system. Actually, consoles are dynamically created and destroyed during your system's lifetime.

The different login: prompts are spawned by the init process, which knows what to do by reading the file /etc/inittab; this very file specifies where getty should be invoked. You can play with inittab even if you don't completely understand it: to open more (or fewer) than 6 consoles for login, you can simply duplicate (or remove) lines. You must be careful, however, about the first field in the line---it is a unique ``key'' for the line, and it must be exactly two letters long.

My choice for console login sessions above 9 is cA, cB and so on, with the first nine entries c1 through c9.

A more interesting, and memory-saving, approach to your Linux session is to spawn only one or two gettys using /etc/inittab, and dynamically allocate other as you need them. There are a number of ways to spawn a new console:

What's the Difference?

The first proposed approach requires no intervention on your side---you should invoke the gpm server and the gpm-root client only at bootup, which you're already supposed to do. The gpm-root client then takes care of it all. Actually, a console is created only by opening it, so little more than fork() and exec() is required. Cleaning up is performed when the child process dies.

The other approaches are explained in the documentation for kbd-0.90, and are slightly more difficult only in that you need to change your keyboard configuration again, run an extra daemon program, or retrieve an extra package---open isn't part of the kbd package. The extra effort is small, because all of the hard work is implemented in the kernel.

Changing the Text Mode

Older versions of Linux couldn't allow console resizing, and a single video mode should be used for the console from boot to shutdown, and it usually was the bare 80x25. Linux-95 (Linux-1.2) allows console resizing. The user program SVGATextMode, despite its cumbersome name, is a nice utility to change the appearance of your text console on-the-fly.

The tool makes use of the ioctl(VT_RESIZE) system call to change the way the video buffer is managed in the kernel, and modifies the internal registers in your video board in order to send the right signals to your monitor. The program must run with root permissions because both tasks are privileged. SVGATextMode isn't alone in the field of console resizing, but it currently is the most flexible choice.

Installing the program is easy---just make && make install. Then configure the file /etc/TextConfig---you need to tell SVGATextMode which chipset is in your video board. The TextConfig file is full of helpful comments.

The single tricky task is resequencing running applications to the new tty size. The configuration file provides a ResetProg line, where you can put a pathname of an executable file that will handle this; it will generally consist of sending SIGWINCH to applications, as outlined in the sample ResetProg.

The definitions for the specific modes are modeled on the XF86Config lines. The X-Windows configuration documentation and any previous experience with with X-Windows configuration can help in playing with text modes. If you're going to fine-tune your X-Windows screen, you can easily run your tests with SVGATextMode. Its fast cycle time makes trial-and-error better because you needn't restart the X server for each trial. Fine-tuning screen timings for text modes can lead to a good configuration to be pasted in your XF86Config file. Alternately, if you have set up X-Windows already, you can use that knowledge to set up SVGATextMode.

Other facilities offered by SVGATextMode are automatic font loading and cursor reshaping. This last feature alone is a good reason to run SVGATextMode on your laptop---no more kernel patch to have a block cursor.

Problems Related to Console Resizing

If you use SVGATextMode, especially on small machines, you'll notice that sometimes console resizing will fail, even if you have plenty of swap available, and sometimes even with plenty of RAM. The problem is related to the kind of memory needed; the kernel needs to complete the system call (an ioctl()) atomically, and it needs to get a contiguous chunk of memory for each active console. There's no time to swap out some process or to shrink the buffer cache, and the kernel keeps only 1/64 of the available RAM for these ``urgent'' issues. As a result, the smaller the box, the more consoles you use, the more you're prone to fail resizing. Resizing to a smaller estate won't always help, because the kernel must be sure to have place for all the active consoles before it starts copying video data to the new area, and only at the end can the old buffer be released. If it fails, simply try again; it will probably succeed the second time.

Another issue is the role of the ResetProg. Why do some applications do resize well (like jed), others become completely stuck (like selection) and still others need to be sent the SIGWINCH signal? Because a resizing of the surrounding window is an asynchronous event, which doesn't fit the normal environment of the application.

Applications belong to three types: over-attentive ones look at the window size often, and perceive the new situation right when it happens; more conventional applications wait for an asynchronous notification of the event (a signal, namely SIGWINCH, for WINdow CHange), and respond to the notification in the right way; and some applications simply don't respond to changes in window size, and ignore SIGWINCH---the current version of selection was written before console resizing was available. Thus, while a resizing xterm sends SIGWINCH by itself, a resizing console doesn't send anything, and an external ResetProg is needed to fill the gap.

Tools for the Text Console

The following tools work particularly well on the text console, sometimes even better than in graphics mode.

Further Readings

All the tools described above come with manual pages or info files. mc has a good internal help utility. gpm-root and the lisp library t-mouse.el are part of the gpm package.

Alessandro Rubini is taking his PhD course in computer science and is breeding two small Linux boxes at home. Wild by his very nature, he loves trekking, canoeing and riding his bike. He wrote gpm, and can be reached as rubini@ipvvis.unipv.it.

Article Response Form

Copyright Notice