Logo Computer scientist,
engineer, and educator
• Software • Utility corner

pi-button-pipe — A GPIO button watcher for Raspberry Pi and similar devices

Version 0.0.1, January 2013

What is this?

pi-button-pipe is a simple daemon for reading interrupts from the GPIO pins of a Raspberry Pi or similar device, and making them available as a stream of data that can be read by another program. It is specifically designed to handle simple, normally-open pushbuttons that pull up the GPIO pins from ground to supply (that is, it triggers on the rising edge of the pin voltage).

pi-button-pipe works without polling, can monitor several pins at once, and does not need to run as root (although a root step is needed to initialize the pin configuration — see below). It does not (or should not) need additional de-bouncing hardware on the pushbuttons, as pi-button-pipe debounces both on the closing and opening of the switch contacts. pi-button-pipe uses a named pipe for communication with the consumer process, whatever that is. Data from the program is simply a stream of decimal numbers corresponding to the pins that were toggled, so it should be easy to integrate with other software.

pi-button-pipe is written in plain C, and does not depend on any additional libraries.

Building and installation

To build from source, in general, unpack the source bundle and run make, followed by make install. The source bundle includes a compiled binary for Raspberry Pi. The install process writes the binary into /usr/bin, although the program is not at all fussy about where it is installed.

Basic operation

In normal operation, pi-button-pipe is invoked with a list of pins to monitor, like this:
# pi-button-pump 23 24 25
It is assumed that each of these pins is attached to a pushbutton that will raise the pin voltage when it is depressed. The program opens a named pipe called /tmp/pi-button-pump and, every time a button is pressed, the pin number is written to the pipe as a decimal number. Meanwhile, the consumer of the pushbutton data reads the pipe. If you simple use cat to read the data, you might see something like this:
$ cat /tmp/pi-buttons
Notice that the consumer need not run as root.

The pipe filename is (sorry) not configurable at present, except by editing the code. If the pipe does not exist, the the program will create it if it can. However, it's important to understand that a Linux pipe is not like a socket — it is intended for one-time use for communication between a single pair of processes. What this means is that both processes will block until both are attached to the pipe. Then, when one process exits, the pipe will break, and the other process will also exit (via a signal). The practical result is that you can't just start pi-button-pipe at boot time, and then have multiple processes connect to it, either conucrrently or one at a time — pi-button-pipe and its consumer must be started as a pair.

Running as a non-root user

pi-button-pipe will run as a non-root user, provided that the relevant pins have been 'exported' first. To export a pin is to tell the kernel to expose in the directory /sys/class/gpio another directory named after the pin, and which contains pseudo-files that can be used to read and write the pin. It is also necessary to set the required pins to input mode, and to set them to interrup on the rising edge. You might also want to 'unexport' the pins afterwards, to avoid them being used inadvertently by other processes. These operations do require root privileges.

To make non-root operation easier, pi-button-pipe provides a way to nothing but export and unexport certain pins; these operations can be run as root. To do this, use the -e (export) and -u (unexport) command-line switches. Then the rest of the work can be done by running as an ordinary user, with the -n switch to indicate that the program should not attempt to export or unexport any pins.

For example, the monitor pins 23, 24, and 25 as a non-root user, use the following commands:

$ sudo pi-button-pump -e 23 24 25 # Export pins
$ pi-button-pump -n 23 24 25      # Do the work
$ sudo pi-button-pump -u 23 24 25 # Unexport pins
# Now start the consumer process
If you're running as a non-root user, you might need to give some thought to the permissions assigned to the pipe /tmp/pi-buttons, particularly if it will be read by a process owned by a different user.


To test the program without a consumer, use the -d switch; this will cause it to write the pin numbers to the console rather than the pipe. If nothing at all seems to be happening, check that the pin voltage is actually changing, e.g., by running gpio readall.


Copyright © 1994-2013 Kevin Boone. Updated Jan 09 2014