Raspberry Pi IoT In C - The Linux GPIO Driver
Written by Harry Fairhead   
Monday, 20 September 2021
Article Index
Raspberry Pi IoT In C - The Linux GPIO Driver
The GPIO Character Device

If you know about Sysfs you might have missed that the Sysfs approach to GPIO is deprecated - so how should you do it? This is an extract from the newly-published Raspberry Pi IoT in C, Second Edition.

Raspberry Pi And The IoT In C Second Edition

By Harry Fairhead


Buy from Amazon.


  1. Why Pi For IoT?
  2. Getting Started
  3. Getting Started With The GPIO
  4. Simple Output
  5. Some Electronics
  6. Simple Input
  7. GPIO The Linux Way
       Extract 1:The Linux GPIO Driver 
  8. Advanced Input – Events, Threads, Interrupts
       Extract 1: Events & Interrupts 
  9. Pulse Width Modulation - Servos And More
       Extract 1:Basic Pulse Width Modulation 
  10. Using The I2C Bus
  11. The DHT22 Sensor Implementing A Custom Protocol
  12. Exploring - 1‑Wire Bus Basics ***NEW!
  13. Using iButtons
  14. DS18B20 Temperature Sensor
      Extract 1: The DS18B20 Temperature Sensor 
  15. The Multidrop 1‑Wire Bus
  16. The Serial Port
      Extract 1: 1-wire Via Serial 
  17. Getting Started With The SPI Bus
  18. A to D With The SPI Bus
  19. Connecting With The Web - Sockets
  20. Memory-Mapped GPIO
  21. Almost Real-Time Linux
  22. Appendix I GPIO Sysfs Interface



GPIO The Linux Way

Until recently the standard way to work with GPIO in Linux was to use the sysfs interface and you will see a lot of articles advocating its use and you will encounter many programs making use of it. Sysfs was deprecated in Linux 4.8 at the end of 2016 and is due for removal from the kernel in 2020. Of course, it takes time for Linux distributions to make use of the latest kernels. At the time of writing Pi OS, formerly Raspbian, is using Linux 4.19 released two years earlier. Nevertheless, Sysfs gpio will soon be removed and while you still need to know about it to cope with legacy software, you shouldn’t use it for new projects. You can find out how it works in Appendix I.

Its replacement is the GPIO character device and, while this looks superficially like the old sysfs interface, it has many major differences. Although it has some advantages, it also is slightly more complex and can no longer be used from the command line – it is a program-only interface. This said, there are some simple utility programs that are fairly standard and allow GPIO control from the command line. These are covered in the first part of the chapter, even though they are unlikely to be the main way that you work with the new interface. There is also a wrapper library called gpiod which isn’t necessary for simple access to the GPIO lines. If you want to know more see - Raspberry Pi IOT in C With Linux Drivers, ISBN:9781871962642

Why Integrate GPIO With Linux?

You might ask, given that we have the BCM 2835 library, why bother with a Linux-based approach? The answer is that the GPIO character driver is standardized across Linux. That is, your program should work with perhaps minor tweaks if you move it from a Raspberry Pi to another machine that has GPIO hardware. In addition, access to the GPIO driver doesn’t require special permissions and you don’t need direct access to memory. It is also a very easy way to make use of I/O events from user space, which makes it sometimes useful to use in conjunction with the BCM 2835 library.

A key principle of Linux is that everything is a file or a folder. As far as possible, Linux deals with external hardware by treating it as if it was a file system. This is reasonable because external hardware either wants to receive data as commands or something to store or display, or to send data as responses or user input. So most hardware interacts with Linux as a source or a sink of data and this is exactly what a file is all about. 

This "everything is a file" approach only really fails when issues of performance enter the picture. Accessing a piece of hardware as if it was a file when it isn't can be slow. In normal use direct memory access is much faster and it is what the BCM 2835 library is all about.

So file-based access to the hardware can be slow, but it has the huge advantage that it is language-independent. Every language has the facilities needed to open, read/write and close a file and so has the facilities needed to work with hardware via the file system. 

It also has the advantage that it works with Linux rather than just ignoring it. The system knows about files and understands how to work with them. This allows it to offer advanced features like interrupts to GPIO users that fit in with the way other Linux interrupts work, more of this in the next chapter.

To be clear if you want to make use of interrupts without writing your own kernel modules, then the GPIO character driver is the only way to do it.

It may seem crazy, especially if you know how the underlying hardware works, to treat a single GPIO line as it if was a file, but it works. Files are a fundamental data type in Linux and a GPIO line is something you read from or write to, just like a file. From the Linux point of view it makes perfect sense. The big problem is that the details of how hardware is represented as a file system is poorly documented and you have to find out about it by guesswork, trial and error, reverse engineering, or by reading code that makes use of it. 

The original way to work with GPIO lines as a file was the sysfs system, which made each line and various aspects of using the GPIO system into files and directories. You worked with the hardware by reading from and writing to the files and you could do this from the command line using cat and echo. This was simple, but there were restrictions and some poor design.

The replacement for sysfs is still file-based but a slightly different sort of file. Devices like the keyboard, serial port and so on are examples of character devices and these are represented by character files. A general file supports operations such as seek that make no sense for a character file – what does it mean to rewind a serial port or keyboard? Character files are simple but to allow some control over the devices that they represent we need something more than just file reading and writing. This is solved using the ioctl, short for “io-control”, system call. This is simple, but it takes us away from the pure idea that devices are files. Now they are files with special control features added. What is difficult is that each device has its own set of control commands or “requests”. This makes working with GPIO character device less than intuitive. You could say that sysfs was intuitive but flawed and GPIO character device is opaque but better designed.

Last Updated ( Monday, 20 September 2021 )