Skip to content
Digital Rhyme
Small Linux development board beside a laptop and simple driver workflow sketches

hello_kmod.c Source

A beginner character-device module with build, load, test, and unload flow.

1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Minimal Linux kernel module example.
4 *
5 * This module creates /dev/hello_kmod. Reading from it returns a short
6 * message. It is intentionally small so the basic driver shape is visible.
7 */
8
9#include <linux/device.h>
10#include <linux/fs.h>
11#include <linux/init.h>
12#include <linux/module.h>
13#include <linux/uaccess.h>
14
15#define DEVICE_NAME "hello_kmod"
16#define CLASS_NAME "hello_class"
17
18static int major_number;
19static struct class *hello_class;
20static struct device *hello_device;
21static const char message[] = "hello from a tiny kernel driver\n";
22
23static int hello_open(struct inode *inode, struct file *file)
24{
25 pr_info("hello_kmod: device opened\n");
26 return 0;
27}
28
29static int hello_release(struct inode *inode, struct file *file)
30{
31 pr_info("hello_kmod: device closed\n");
32 return 0;
33}
34
35static ssize_t hello_read(struct file *file, char __user *buffer,
36 size_t length, loff_t *offset)
37{
38 size_t message_len = sizeof(message) - 1;
39 size_t bytes_to_copy;
40
41 if (*offset >= message_len)
42 return 0;
43
44 bytes_to_copy = min(length, message_len - (size_t)*offset);
45
46 if (copy_to_user(buffer, message + *offset, bytes_to_copy))
47 return -EFAULT;
48
49 *offset += bytes_to_copy;
50 return bytes_to_copy;
51}
52
53static const struct file_operations hello_fops = {
54 .owner = THIS_MODULE,
55 .open = hello_open,
56 .read = hello_read,
57 .release = hello_release,
58};
59
60static int __init hello_init(void)
61{
62 major_number = register_chrdev(0, DEVICE_NAME, &hello_fops);
63 if (major_number < 0) {
64 pr_err("hello_kmod: failed to register char device\n");
65 return major_number;
66 }
67
68 hello_class = class_create(CLASS_NAME);
69 if (IS_ERR(hello_class)) {
70 unregister_chrdev(major_number, DEVICE_NAME);
71 return PTR_ERR(hello_class);
72 }
73
74 hello_device = device_create(hello_class, NULL, MKDEV(major_number, 0),
75 NULL, DEVICE_NAME);
76 if (IS_ERR(hello_device)) {
77 class_destroy(hello_class);
78 unregister_chrdev(major_number, DEVICE_NAME);
79 return PTR_ERR(hello_device);
80 }
81
82 pr_info("hello_kmod: loaded as /dev/%s with major %d\n",
83 DEVICE_NAME, major_number);
84 return 0;
85}
86
87static void __exit hello_exit(void)
88{
89 device_destroy(hello_class, MKDEV(major_number, 0));
90 class_destroy(hello_class);
91 unregister_chrdev(major_number, DEVICE_NAME);
92 pr_info("hello_kmod: unloaded\n");
93}
94
95module_init(hello_init);
96module_exit(hello_exit);
97
98MODULE_LICENSE("GPL");
99MODULE_AUTHOR("Digital Rhyme Knowledge Base");
100MODULE_DESCRIPTION("Minimal Linux character device kernel module");