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