Linux Device Driver Tutorial Part 9 – Procfs in Linux

This article is a continuation of the  Series on Linux Device Driver, and carries on the discussion on character drivers and their implementation.This is the Part 9 of Linux device driver tutorial. Now we will discuss ProcFS in Linux.

Introduction

Operating system segregates virtual memory into kernel space and user space.  Kernel space is strictly reserved for running the kernel, kernel extensions, and most device drivers. In contrast, user space is the memory area where all user mode applications work and this memory can be swapped out when necessary. 
There are many ways to Communicate between the User space and Kernel Space, they are:
  • IOCTL
  • Procfs
  • Sysfs
  • Configfs
  • Debugfs
  • Sysctl
  • UDP Sockets
  • Netlink Sockets

In this tutorial we will see Procfs.

Procfs in Linux

Introduction

Many or most Linux users have at least heard of proc. Some of you may wonder why this folder is so important.

On the root, there is a folder titled “proc”. This folder is not really on /dev/sda1 or where ever you think the folder resides. This folder is a mount point for the procfs (Process Filesystem) which is a filesystem in memory. Many processes store information about themselves on this virtual filesystem. ProcFS also stores other system information.

It can act as a bridge connecting the user space and the kernel space. User space program can use proc files to read the information exported by kernel. Every entry in the proc file system provides some information from the kernel.

The entry “meminfo”  gives the details of the memory being used in the system.
To read the data in this entry just run

cat /proc/meminfo

Similarly the “modules” entry gives details of all the modules that are currently a part of the kernel.

cat /proc/modules

It gives similar information as lsmod. Like this more proc entries are there.

  • /proc/devices — registered character and block major numbers
  • /proc/iomem — on-system physical RAM and bus device addresses
  • /proc/ioports — on-system I/O port addresses (especially for x86 systems)
  • /proc/interrupts — registered interrupt request numbers
  • /proc/softirqs — registered soft IRQs
  • /proc/swaps — currently active swaps
  • /proc/kallsyms — running kernel symbols, including from loaded modules
  • /proc/partitions — currently connected block devices and their partitions
  • /proc/filesystems — currently active filesystem drivers
  • /proc/cpuinfo — information about the CPU(s) on the system

Most proc files are read-only and only expose kernel information to user space programs.

proc files can also be used to control and modify kernel behavior on the fly. The proc files needs to be writtable in this case.

For example, to enable IP forwarding of iptable, one can use the command below,

echo 1 > /proc/sys/net/ipv4/ip_forward

The proc file system is also very useful when we want to debug a kernel module. While debugging we might want to know the values of various variables in the module or may be the data that module is handling. In such situations we can create a proc entry for our selves and dump what ever data we want to look into in the entry.

We will be using the same example character driver that we created in the previous post to create the proc entry.

The proc entry can also be used to pass data to the kernel by writing into the kernel, so there can be two kinds of proc entries.

  1. An entry that only reads data from the kernel space.
  2. An entry that reads as well as writes data into and from kernel space.

Creating Procfs Entry

The creation of proc entries has undergone a considerable change in kernel version 3.10 and above. In this post we will see one of the methods we can use in linux kernel version 3.10 and above let us see how we can create proc entries in version 3.10 and above.

The function is defined in proc_fs.h.

Where,

<name> : The name of the proc entry
<mode> : The access mode for proc entry
<parent> : The name of the parent directory under /proc. If NULL is passed as parent, the /proc directory will be set as parent.
<proc_fops> : The structure in which the file operations for the proc entry will be created.

For example to create a proc entry by the name “etx_proc” under /proc the above function will be defined as below,

This proc entry should be created in Driver init function.

If you are using kernel version below 3.10, please use below functions to create proc entry.

create_proc_read_entry()
create_proc_entry() 

Both of these functions are defined in the file linux/proc_fs.h. 

The create_proc_entry is a generic function that allows to create both read as well as write entries.
create_proc_read_entry is a function specific to create only read entries.

Its possible that most of the proc entries are created to read data from the kernel space that is why the kernel developers have provided a direct function to create a read proc entry.

Procfs File System

Now we need to create file_operations structure proc_fops in which we can map the read and write functions for the proc entry.

This is like a device driver file system. We need to register our proc entry filesystem. If you are using kernel version below 3.10, this will not be work. There is a different method.

Next we need to add the all functions to the driver.

Open and Release Function

This functions are optional.

Write Function

The write function will receive data from the user space using the function copy_from_user into a array “etx_array”.

Thus the write function will look as below.

Read Function

Once data is written to the proc entry we can read from the proc entry using a read function, i.e transfer data to the user space using the function copy_to_user function.

The read function can be as below.

 

Remove Proc Entry

Proc entry should be removed in Driver exit function using the below function.

void remove_proc_entry(const char *name, struct proc_dir_entry *parent);

Example:

Complete Driver Code

This code will work for the kernel above 3.10 version. I just took the previous tutorial driver code and update with procfs.

MakeFile

Building and Testing Driver

  • Build the driver by using Makefile (sudo make)
  • Load the driver using sudo insmod driver.ko
  • Check our procfs entry using ls in procfs directory

[email protected]:ls /proc/

    filesystems      iomem      kallsyms      modules    partitions

  • Now our procfs entry is there under /proc directory.
  • Now you can read procfs variable using cat.

[email protected]:  cat /proc/etx_proc

try_proc_array

  • We initialized the etx_array with “try_proc_array”. That’s why we got “try_proc_array”.
  • Now do proc write using echo command and check using cat.

[email protected]: echo "device driver proc" > /proc/etx_proc

[email protected]:  cat /proc/etx_proc

device driver proc

  • We got the same string which was passed to the driver using procfs.

This is the simple example using procfs in device driver. This is just a basic. I hope this might helped you.

Download our new Android app. You can learn all Embedded Tutorials from your Android Phone easily.

Click Here to Download App!