Search

Creating a FIFO in linux kernel

FIFO is a first in first out data structure that which can be used to hold any kind of data. Linux kernel provides useful APIs to make creation and use of FIFO data structure easy.

The first step in creation of FIFO is to define the FIFO required with the type of data it will be holding using



Once the FIFO has been defined we can use a number of functions available to add,remove, check the FIFO. To put data into the FIFO



To take the date out of the FIFO



Just to see the above functions in use we will create a proc entry which will output one data from a FIFO that gets created as soon as the module is inserted into the kernel.

To create a module with 6 char entries



An array of values to be added to the FIFO



To add the entries into the FIFO when the module gets inserted into the kernel, the init function needs to call the kfifo_put function



Once the fifo has been created, we can extract one data at a time using the function kfifo_get . To ensure that only one data is read from the FIFO each time we use the cat command on the proc entry extra checks and flags are needed



The function kfifo_is_empty returns true when the fifo is empty else it returns false.

The full code for creation of the proc entry called "fifo" which will output one data value at a time is:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include<linux/sched.h>
#include <asm/uaccess.h>
#include<linux/slab.h>
#include<linux/kfifo.h>
#define FIFO_SIZE 32
ssize_t size;
int flag=1;
char entries[]={'a','b','c','d','e','f','g','h'};
DEFINE_KFIFO(test,char,FIFO_SIZE);
ssize_t read_proc(struct file *filp,char *buf,size_t count,loff_t *offp )
{
int ret,size;
char *temp,*start;
temp=kmalloc(sizeof(char)*10,GFP_KERNEL);
start=temp;
if(flag==0) {
size=0;
flag=1;
printk(KERN_INFO "in if");
}
else {
if(kfifo_is_empty(&test)) {
temp="FIFO empty\n";
printk(KERN_INFO "in empty");
size=strlen(temp);
simple_read_from_buffer(buf,count,offp,temp,size);
}
else {
ret=kfifo_get(&test,temp);
temp=temp+1;
printk(KERN_INFO "in else %d",ret);
*temp='\n';
simple_read_from_buffer(buf,count,offp,start,ret+1);
size=ret+1;
}
flag=flag-1;
}
return size;
}
struct file_operations proc_fops = {
read: read_proc
};
void create_new_proc_entry(void)
{
proc_create("fifo",0,NULL,&proc_fops);
}
int proc_init (void) {
int i=0;
create_new_proc_entry();
for(i=0;i<6;i++)
kfifo_put(&test,entries[i]);
return 0;
}
void proc_cleanup(void) {
remove_proc_entry("fifo",NULL);
}
MODULE_LICENSE("GPL");
module_init(proc_init);
module_exit(proc_cleanup);


If the file is saved as proc_read_fifo.c, it can be compiled using

ifneq ($(KERNELRELEASE),)
obj-m := proc_read_fifo1.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
endif
view raw makefile hosted with ❤ by GitHub


To test the code, once the compile and insert the code



Read the proc entry using the cat command

The output shows that every call to read the entry removes one item from the fifo and when all entries are removed "FIFO empty" message gets printed.

No comments:

Post a Comment