The codes on the post are from the Linux kernel module programming guide 1.
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h> // for char dev related functions
#include <linux/uaccess.h> // for put_user()
int init_module(void);
void cleanup_module(void);
static int device_open(struct inode* inode, struct file* file);
static int device_release(struct inode* inode, struct file* file);
static ssize_t device_read(struct file* filp, char* buffer, size_t length, loff_t* offset);
static ssize_t device_write(struct file* filp, const char* buffer, size_t length, loff_t* offset);
#define SUCCESS 0
#define DEVICE_NAME "chardev"
#define BUF_LEN 80
static int major;
static int device_opened = 0;
static char msg[BUF_LEN];
static char *msg_ptr;
static struct file_operations fops = {
	.open = device_open,
	.release = device_release,
	.read = device_read,
	.write = device_write
};
int init_module(void) {
	major = register_chrdev(0, DEVICE_NAME, &fops);
	if (major < 0) {
		printk(KERN_ALERT "Registering char device failed with %d\n", major);
		return major;
	}
	printk(KERN_INFO "chardev::Major number: %d\n", major);
	printk(KERN_INFO "chardev::Device name: %s\n", DEVICE_NAME);
	return SUCCESS;
}
void cleanup_module(void) {
	unregister_chrdev(major, DEVICE_NAME);
}
static int device_open(struct inode* inode, struct file* file) {
	static int counter = 0;
	if (device_opened) return -EBUSY;
	device_opened++;
	sprintf(msg, "I already told you %d times. Hello world!\n", counter++);
	msg_ptr = msg;
	try_module_get(THIS_MODULE);
	return SUCCESS;
}
static int device_release(struct inode* inode, struct file* file) {
	device_opened--;
	module_put(THIS_MODULE);
	return 0;
}
static ssize_t device_read(struct file* filp, char* buffer, size_t length, loff_t* offset) {
	int bytes_read = 0;
	if (*msg_ptr == 0) return 0;
	while (length && *msg_ptr) {
		put_user(*(msg_ptr++), buffer++);
		length--;
		bytes_read++;
	}
	return bytes_read;
}
static ssize_t device_write(struct file* filp, const char* buffer, size_t length, loff_t* offset) {
	printk(KERN_ALERT "This operation is not supported\n");
	return -EINVAL;
}
After installing the module, we have to create a device instance and assign a minor number as follows.
sudo mknod /dev/chardev c 242 0
Then we can open the device using the following command.
$ cat /dev/chardev
I already told you 0 times. Hello world!
$ cat /dev/chardev
I already told you 1 times. Hello world!
$ cat /dev/chardev
I already told you 2 times. Hello world!
- 
      
Peter Jay Salzman, Micheal Burian and Ori Pomerantz, “The Linux Kernel Module Programming Guide,” 2001. ↩
 
Comments