Challenge

Project 1 - Develop the full featured char driver as a loaded module

#include <linux/module.h>

#include <linux/fs.h>

#include <linux/uaccess.h>

#include <linux/slab.h>

#include <linux/proc_fs.h>

#include <linux/seq_file.h>

#include <linux/semaphore.h>

#define CHAR_DRIVER_NAME "char_driver"

#define PROC_FILENAME "char_driver_size"

MODULE_LICENSE("GPL");

// Module parameters

static int max_memory_size = 8192; // Default value

// Device structure

struct char_driver_dev {

struct semaphore sem;

char *data;

size_t size;

loff_t offset;

int is_open;

};

static struct char_driver_dev *char_dev;

static int char_driver_open(struct inode *inode, struct file *filp)

{

if (down_interruptible(&char_dev->sem))

return -ERESTARTSYS;

if (char_dev->is_open) {

up(&char_dev->sem);

return -EBUSY;

}

char_dev->is_open = 1;

char_dev->offset = 0;

up(&char_dev->sem);

return 0;

}

static int char_driver_release(struct inode *inode, struct file *filp)

{

if (down_interruptible(&char_dev->sem))

return -ERESTARTSYS;

char_dev->is_open = 0;

up(&char_dev->sem);

return 0;

}

static ssize_t char_driver_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)

{

// Implementation of read operation

}

static ssize_t char_driver_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)

{

// Implementation of write operation

}

static loff_t char_driver_llseek(struct file *filp, loff_t offset, int whence)

{

// Implementation of seek operation

}

static const struct file_operations char_driver_fops = {

.owner = THIS_MODULE,

.open = char_driver_open,

.release = char_driver_release,

.read = char_driver_read,

.write = char_driver_write,

.llseek = char_driver_llseek,

};

// Procfs functions

static int char_driver_proc_show(struct seq_file *m, void *v)

{

seq_printf(m, "Memory size allocated: %zu bytes\n", char_dev->size);

return 0;

}

static int char_driver_proc_open(struct inode *inode, struct file *file)

{

return single_open(file, char_driver_proc_show, NULL);

}

static const struct file_operations char_driver_proc_fops = {

.owner = THIS_MODULE,

.open = char_driver_proc_open,

.read = seq_read,

.llseek = seq_lseek,

.release = single_release,

};

static int __init char_driver_init(void)

{

dev_t dev = 0;

int result;

// Register char device

result = alloc_chrdev_region(&dev, 0, 1, CHAR_DRIVER_NAME);

if (result < 0) {

printk(KERN_WARNING "char_driver: can't get major %d\n", MAJOR(dev));

return result;

}

// Initialize device structure

char_dev = kmalloc(sizeof(struct char_driver_dev), GFP_KERNEL);

if (!char_dev) {

result = -ENOMEM;

goto fail_malloc;

}

char_dev->data = kmalloc(max_memory_size, GFP_KERNEL);

if (!char_dev->data) {

result = -ENOMEM;

goto fail_malloc_data;

}

char_dev->size = max_memory_size;

char_dev->is_open = 0;

char_dev->offset = 0;

sema_init(&char_dev->sem, 1);

// Initialize char device

cdev_init(&char_dev->cdev, &char_driver_fops);

char_dev->cdev.owner = THIS_MODULE;

result = cdev_add(&char_dev->cdev, dev, 1);

if (result) {

printk(KERN_WARNING "char_driver: can't add cdev to region\n");

goto fail_cdev_add;

}

// Create procfs entry

proc_create(PROC_FILENAME, 0, NULL, &char_driver_proc_fops);

printk(KERN_INFO "char_driver: module loaded\n");

return 0;

fail_cdev_add:

kfree(char_dev->data);

fail_malloc_data:

kfree(char_dev);

fail_malloc:

unregister_chrdev_region(dev, 1);

return result;

}

static void __exit char_driver_exit(void)

{

dev_t dev = 0;

dev = MKDEV(MAJOR(dev), MINOR(dev));

unregister_chrdev_region(dev, 1);

cdev_del(&char_dev->cdev);

kfree(char_dev->data);

kfree(char_dev);

remove_proc_entry(PROC_FILENAME, NULL);

printk(KERN_INFO "char_driver: module unloaded\n");

}

module_init(char_driver_init);

module_exit(char_driver_exit);

Your portfolio, next

Ship work like this
in your own course.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.