Challenge

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

Project Overview:

The project involves creating a Linux kernel module for a character device driver. The module provides functionality such as open, release, read, write, and seek operations on a character device. Additionally, a /proc entry is created to display the size of the memory allocated to the character device.

Code Steps:

  1. Header Files:

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/fs.h>

#include <linux/init.h>

#include <linux/slab.h>

#include <linux/cdev.h>

#include <asm/uaccess.h>

#include <linux/proc_fs.h>

  1. These are necessary header files for kernel module development, providing access to essential kernel functions and structures.

Constants and Variables:

#define DEVICE_NAME "chardev"

#define PROCFS_NAME "char_driver_size"

#define MAX_SIZE 1024

Definitions for device name, procfs name, and maximum memory size.

Global Variables:

static int Major;

static int Device_Open = 0;

static char msg[MAX_SIZE];

static char *msg_Ptr;

static int size_of_msg = 0;

static struct proc_dir_entry *proc_file;

static struct cdev chardev;

Variables to store major number, device open status, message buffer, proc file, and the character device structure.

File Operations Structure:

static const struct file_operations chardev_fops = { .owner = THIS_MODULE, .read = chardev_read, .write = chardev_write, .open = chardev_open, .release = chardev_release, .llseek = chardev_llseek };

Defines the file operations (open, release, read, write, seek) for the character device.

Open Operation:

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

{

if (Device_Open) return -EBUSY;

Device_Open++;

msg_Ptr = msg;

try_module_get(THIS_MODULE);

return 0;

}

Increments open count, sets the message pointer, and increments the module usage count.

Release Operation:

static ssize_t chardev_read(struct file *filp, char *buf, size_t count, loff_t *f_pos) { int bytes_read = 0; if (*msg_Ptr == 0) return 0; while (count && *msg_Ptr) { put_user(*(msg_Ptr++), buf++); count--; bytes_read++; } return bytes_read; }

Read Operation:

static ssize_t chardev_read(struct file *filp, char *buf, size_t count, loff_t *f_pos) { int bytes_read = 0; if (*msg_Ptr == 0) return 0; while (count && *msg_Ptr) { put_user(*(msg_Ptr++), buf++); count--; bytes_read++; } return bytes_read; }

Reads data from the device to the user space.

Write Operation:

static ssize_t chardev_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos) { if (count > MAX_SIZE) count = MAX_SIZE; if (copy_from_user(msg, buf, count)) return -EFAULT; size_of_msg = count; return count; }

Writes data from user space to the device.

Seek Operation:

static loff_t chardev_llseek(struct file *filp, loff_t off, int whence) { loff_t newpos; switch (whence) { case 0: /* SEEK_SET */ newpos = off; break; case 1: /* SEEK_CUR */ newpos = filp->f_pos + off; break; case 2: /* SEEK_END */ newpos = size_of_msg + off; break; default: /* can't happen */ return -EINVAL; } if (newpos < 0) return -EINVAL; filp->f_pos = newpos; return newpos; }

Implements seek functionality for the device.

Initialization:

static int __init chardev_init(void)

  • Allocates a major number dynamically.
  • Initializes the character device structure.
  • Adds the character device to the kernel.
  • Creates the proc file.

Build Steps (Makefile):

obj-m := proj1_chardev.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

  • obj-m specifies the module target.
  • all builds the module.
  • clean removes build artifacts.

This project serves as a foundational example of creating a simple character device driver for Linux. Real-world applications could include creating virtual devices for communication between user-space and kernel-space, implementing custom I/O operations, or developing interfaces for hardware devices.

For instance, a character device driver could be used to interface with custom hardware peripherals, sensors, or actuators. It allows user-space applications to interact with the underlying hardware through standard file operations.

This project provides a starting point for understanding Linux kernel module development, character device operations, and interaction with user-space applications. It covers essential concepts such as dynamic allocation, file operations, and kernel-User communication, paving the way for more complex driver development.

To add the module to the Kernel configuration Kconfig build system with tristate option, we need to perform the following steps:

1.Create a Kconfig file in the root directory of your driver source code. This file will define the configuration options for your driver.

2.Define the tristate option for your driver module in the Kconfig file.

3.The tristate option allows the user to choose between building the module as a loadable module, built-in module or not building the module at all.

4.Define the maximum memory size configuration option for your driver module in the Kconfig file.

5.This will allow the user to configure the maximum amount of memory that can be allocated to the driver. Define the char driver as open, which allows only one user to open the device at a time. Other users should be blocked.

6.Define read and write operations to store data to the dynamically allocated memory and read from it.

7.Implement seek operation to move the offset of the read/write location.

8.Implement Blocked Read /write operation to wait whenever data is not available to read, and when enough memory is not available during write.

9.Create a /proc/char_driver_size file to reflect the size of memory allocated to the char driver.

10.After completing the Kconfig file, add it to the Kbuild system, and build the kernel image with your driver module included.

11.Once the kernel is built, install it, and load the driver module using insmod.

12.Verify the driver functionality by testing the open, read, write, seek, and /proc file operations.

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.