Adding procfs and sysfs interface in your lkml

April 21, 2010

[Warning: This post is a backup recovery from my previous Wordpress blog. All content was automatically converted accessing a MySQL database using a Python script (details). Mostly are in Portuguese but if you are interest I can translate to English. If you found any problem dont’t hesitate to contact me in comments.]

Hi. This post will show how to add two important things about device model in your linux kernel module (lkml). Sysfs is the user-space manifestation of the kernel's structured device model. It's similar to procfs in that both are in-memory filesystem containing information about kernel data structures. Basically:

  • procfs is a generic window into kernel internals
  • sysfs is specific to device model

Information such as process descriptors and sysctls parameters belong to procfs and not sysfs. Note that:Sysfs is not a replacement for procfs.

Lets create two useless (in a practical way) that presents the “idea” behind these constructions.

1. Procfs

The snippet below creates a /proc/coding allowing read or write some content.

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>

/* for proc_dir_entry and create_proc_entry */
#include <linux/proc_fs.h>

/* For sprintf and snprintf */
#include <linux/string.h>

/* For copy_from_user */
#include <linux/uaccess.h>

static char internal_buffer[256];

int buf_read(char *buf, char **start, off_t offset, int count, int *eof, void *data)
{
	int len;
	len = snprintf(buf, count, "%s", internal_buffer);
	return len;
}

static int buf_write(struct file *file, const char *buf, unsigned long count, void *data)
{
	if(count > 255) /* to avoid overflowwwwwwwwww */
		count = 255;

	/* Copies data from user space to kernel space */
	copy_from_user(internal_buf, buf, count);

	/* inserting NULL to end the string */
	internal_buf[count] = '\0';
	return count;
}

int __init proc_init(void) {
	/* Simple */
	struct proc_dir_entry *de = create_proc_entry("coding", 0667, 0);

	/* Set pointers to our functions */
	de->read_proc = buf_read; /* reading */
	de->write_proc = buf_write; /* writing */ 

	/* We initialize our internal_buffer with some text. */
	sprintf(internal_buffer, "www.coding.com.br");
	return 0 ;
}

void __exit proc_cleanup(void) {

	/* We delete our entry */
	remove_proc_entry("coding", NULL);

}

module_init(proc_init);
module_exit(proc_cleanup);

MODULE_LICENSE("GPL");

2. Sysfs

This example only creates a /sys/class/<module-name> directorywith nothing inside. This may not be clear now but remember when I show - in the next posts - some practical use with device node (/dev).

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>

/* for sysfs class creation */
#include <linux/platform_device.h>

static struct class *sysfs_class;

int __init sysfs_init(void) {

	sysfs_class = class_create(THIS_MODULE, "sysfs" );
	return 0 ;
}

void __exit sysfs_cleanup(void) {

	/* We delete our entry */
	class_destroy(sysfs_class);
}

module_init(sysfs_init);
module_exit(sysfs_cleanup);

MODULE_LICENSE("GPL");