The proc file system is an interface between the kernel and the userspace. Every entry in the proc file system provides some information from the kernel.
For eg:
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
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
An entry that only reads data from the kernel space
An entry that reads as well as writes data into and from kernel space.
We will start by creating a proc entry for only reading first and then move to a a proc entry for write.
Creating proc entry:
Kernel provides the following functions to create a 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.
We will first use the create_proc_read_entry to create our entry and then look into create_proc_entry.
The proc entries are basically based on the structure “proc_dir_entry”. Meaning every proc entry that gets created is represented by a structure of the kind
“proc_dir_entry” by the kernel.
The structure “proc_dir_entry” looks as follows in 2.6.33-21
The prototype of the function create_proc_read_entry is
struct proc_dir_entry *create_proc_read_entry(const char *name,
mode_t mode, struct proc_dir_entry *base,
read_proc_t *read_proc, void * data)
name : This the name by which entry will be created under the proc file system.
for eg: if we pass “first_proc_entry” , then it will create a file by the name
first_proc_entry under the /proc directory.
mode : mode sets the permissions for the entry created, if 0 is passed it takes
system default settings
base : Base is the base directory in which the entry should be created, this is
useful when you want to create a proc entry under a sub folder in /proc. If
you pass NULL it will create it under /proc by default
read_proc: read_proc is a pointer to the function that should be called every time
the proc entry is read. The function should be implemented in the
driver. It is this functions which we will use to display what ever data
we want to display to the user.
data : This is not used by the kernel, but is passed as it is to the read_proc
function. The data is used by the driver writer to pass any private data
that has to be passed to the read_proc function. It can be passed as NULL
if no data has to be passed.
Once a module gets registered with the kernel, the corresponding proc entry should also be created. So the call to the function create_read_proc_entry is included in the “init” function of the driver.
Removing a proc entry:
When a module is removed from the kernel, it should also remove any proc entries it created. The function that enables the removal of proc entry is “remove_proc_entry” which has the following prototype
void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
name: Name of the proc entry that has to be removed.
parent: In case the proc entry lies in a subdirectory under the proc filesystem, we
can pass the subdirectories here.
With this introduction to proc filesystem and the corresponding function calls that will allow us to create the entries we can start writing the code to create our first proc entry.