Create Simple Debugfs Object

2 October 2017 ยท 2 minute read

In this article we will create simple debugfs object in /sys/kernel/debug/. Our debugfs object will be able to save some string and return it.

In the first step module creates directory in /sys/kernel/debug/ with name debugfs_test:

subdir = debugfs_create_dir("debugfs_test", NULL);

And adds in this directory file data_file:

data_file = debugfs_create_file("data_file", 0644, subdir, NULL, &data_file_fops);

Module handles reading and writing events with this functions:

static ssize_t data_read(struct file *, char *, size_t, loff_t *);
static ssize_t data_write(struct file *, const char *, size_t, loff_t *);

I also used functions simple_read_from_buffer and simple_write_to_buffer to work with buffers.

You can find source code of this module at the end of this article or in repository

Testing

After compiling and installing this module we will get new directory debugfs_test in /sys/kernel/debug/:

# pwd
/sys/kernel/debug/debugfs_test
# ls -lha
total 0
drwxr-xr-x  2 root root 0 oct  2 18:09 .
drwx------ 32 root root 0 oct  2 18:09 ..
-rw-r--r--  1 root root 0 oct  2 18:09 data_file

We can use function cat and tee for testing:

# echo "simple data" | tee data_file
simple data
# cat data_file
simple data
# echo "next data, simple echo" | tee data_file
next data, simple echo
# cat data_file
next data, simple echo

You can see that this module works like we expected.

Source code

/**
 * @file debugfs.c
 * @author janczer
 * @version 0.1
 */

#include <linux/string.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/debugfs.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("janczer");
MODULE_DESCRIPTION("Simple debugfs object");
MODULE_VERSION("0.1");

char data[PAGE_SIZE]; // variable to store data
int data_len = 0;

static struct dentry *data_file;
static struct dentry *subdir;

// function for handle read and write events
static ssize_t data_read(struct file *, char *, size_t, loff_t *);
static ssize_t data_write(struct file *, const char *, size_t, loff_t *);

const struct file_operations data_file_fops = {
	.owner = THIS_MODULE,
	.write = data_write,
	.read = data_read,
};

static int __init debugfs_init(void)
{
	subdir = debugfs_create_dir("debugfs_test", NULL);
	if (!subdir)
		return -ENOENT;

	data_file = debugfs_create_file("data_file", 0644, subdir, NULL,
			&data_file_fops);
	if (!data_file)
		goto exit;

	return 0;
exit:
	debugfs_remove_recursive(subdir);
	return -ENOENT;
}

static void __exit debugfs_exit(void)
{
	debugfs_remove_recursive(subdir);
}

static ssize_t data_read(struct file *f, char *buffer,
		size_t len, loff_t *offset)
{
	return simple_read_from_buffer(buffer, len, offset, data, data_len);
}

static ssize_t data_write(struct file *f, const char *buffer,
		size_t len, loff_t *offset)
{
	ssize_t ret;

	ret = simple_write_to_buffer(data, PAGE_SIZE, offset, buffer, len);

	if (ret < 0)
		return ret;

	data_len = ret;

	return len;
}

module_init(debugfs_init);
module_exit(debugfs_exit);
comments powered by Disqus
github