Project 1 - Develop the full featured char driver as a loaded module
KConfig:
menuconfig CHARACTER_DEVICE_DRIVER
tristate "Advanced Character Device Driver"
help
This is an advanced character device driver with features like
blocking I/O, dynamic memory, and single-user access.
if CHARACTER_DEVICE_DRIVER
config CHAR_MAX_MEM_SIZE
int "Maximum memory size (in bytes)"
default 1024
help
Configure the maximum memory size for the character device.
endif
Kernel Module Code:
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/mutex.h>
#define DEVICE_NAME "char_driver"
#define PROC_FILENAME "char_driver_size"
static int major;
static char *device_buffer;
static size_t buffer_size;
static size_t read_offset = 0, write_offset = 0;
static size_t max_memory = 1024; // Default max memory size
module_param(max_memory, ulong, 0444);
static wait_queue_head_t read_queue, write_queue;
static struct mutex device_lock;
static struct proc_dir_entry *proc_file;
static ssize_t char_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) {
...
}
static ssize_t char_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) {
...
}
static loff_t char_llseek(struct file *filp, loff_t offset, int whence) {
...
}
static int char_open(struct inode *inode, struct file *filp) {
...
}
static int char_release(struct inode *inode, struct file *filp) {
...
}
static const struct file_operations fops = {
.owner = THIS_MODULE,
.read = char_read,
.write = char_write,
.llseek = char_llseek,
.open = char_open,
.release = char_release,
};
static ssize_t proc_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) {
char buf[128];
int len = snprintf(buf, sizeof(buf), "Buffer size: %zu bytes\n", buffer_size);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static const struct proc_ops proc_ops = {
.proc_read = proc_read,
};
static int __init char_init(void) {
major = register_chrdev(0, DEVICE_NAME, &fops);
if (major < 0) return major;
device_buffer = kzalloc(max_memory, GFP_KERNEL);
if (!device_buffer) return -ENOMEM;
proc_file = proc_create(PROC_FILENAME, 0444, NULL, &proc_ops);
if (!proc_file) {
unregister_chrdev(major, DEVICE_NAME);
kfree(device_buffer);
return -ENOMEM;
}
init_waitqueue_head(&read_queue);
init_waitqueue_head(&write_queue);
mutex_init(&device_lock);
pr_info("Char driver loaded with major %d\n", major);
return 0;
}
static void __exit char_exit(void) {
proc_remove(proc_file);
unregister_chrdev(major, DEVICE_NAME);
kfree(device_buffer);
pr_info("Char driver unloaded\n");
}
module_init(char_init);
module_exit(char_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Advanced Character Device Driver");
MODULE_VERSION("1.0");