Skip to content

Commit 5c60514

Browse files
committed
A simple Linux loadable Kernel Module
1 parent 5766da0 commit 5c60514

File tree

2 files changed

+115
-105
lines changed

2 files changed

+115
-105
lines changed

Makefile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
obj-m += lkm_example.o
2+
all:
3+
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
4+
clean:
5+
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
6+
test:
7+
sudo dmesg -C
8+
sudo insmod lkm_example.ko
9+
sudo rmmod lkm_example.ko
10+
dmesg
Lines changed: 105 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,105 +1,105 @@
1-
#include <linux/init.h>
2-
#include <linux/module.h>
3-
#include <linux/kernel.h>
4-
#include <linux/fs.h>
5-
#include <asm/uaccess.h>
6-
MODULE_LICENSE("GPL");
7-
MODULE_AUTHOR("P Srinivas Rao");
8-
MODULE_DESCRIPTION("A simple Linux loadable Kernel Module.");
9-
MODULE_VERSION("0.01");
10-
11-
#define DEVICE_NAME "lkm_example"
12-
#define EXAMPLE_MSG "Hello, World!\n"
13-
#define MSG_BUFFER_LEN 15
14-
15-
/* Prototypes for device functions */
16-
static int device_open(struct inode *, struct file *);
17-
static int device_release(struct inode *, struct file *);
18-
static ssize_t device_read(struct file *, char *, size_t, loff_t *);
19-
static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
20-
static int major_num;
21-
static int device_open_count = 0;
22-
static char msg_buffer[MSG_BUFFER_LEN];
23-
static char *msg_ptr;
24-
25-
/* This structure points to all of the device functions */
26-
static struct file_operations file_ops = {
27-
.owner = THIS_MODULE,
28-
.read = device_read,
29-
.write = device_write,
30-
.open = device_open,
31-
.release = device_release
32-
};
33-
34-
/* When a process reads from our device, this gets called. */
35-
static ssize_t device_read(struct file *filep, char *buffer, size_t len, loff_t *offset) {
36-
int bytes_read = 0;
37-
/* If we're at the end, loop back to the beginning */
38-
if (*msg_ptr == 0) {
39-
msg_ptr = msg_buffer;
40-
}
41-
42-
/* Put data in the buffer */
43-
while (len && *msg_ptr) {
44-
/* Buffer is in user data, not kernel, so you can't just reference
45-
* with a pointer. The function put_user handles this for us */
46-
put_user(*(msg_ptr++), buffer++);
47-
len--;
48-
bytes_read++;
49-
}
50-
return bytes_read;
51-
}
52-
53-
/* Called when a process tries to write to our device */
54-
static ssize_t device_write(struct file *filep, const char *buffer, size_t len, loff_t *offset) {
55-
/* This is a read-only device */
56-
printk(KERN_ALERT "This operation is not supported.\n");
57-
return -EINVAL;
58-
}
59-
60-
/* Called when a process opens our device */
61-
static int device_open(struct inode *inode, struct file *file) {
62-
/* If device is open, return busy */
63-
if (device_open_count) {
64-
return -EBUSY;
65-
}
66-
device_open_count++;
67-
try_module_get(THIS_MODULE);
68-
return 0;
69-
}
70-
71-
/* Called when a process closes our device */
72-
static int device_release(struct inode *inode, struct file *file) {
73-
/* Decrement the open counter and usage count. Without this, the module would not unload. */
74-
device_open_count--;
75-
module_put(THIS_MODULE);
76-
return 0;
77-
}
78-
79-
static int __init lkm_example_init(void) {
80-
/* Fill buffer with our message */
81-
strncpy(msg_buffer, EXAMPLE_MSG, MSG_BUFFER_LEN);
82-
83-
/* Set the msg_ptr to the buffer */
84-
msg_ptr = msg_buffer;
85-
86-
/* Try to register character device */
87-
major_num = register_chrdev(0, "lkm_example", &file_ops);
88-
89-
if (major_num < 0) {
90-
printk(KERN_ALERT "Could not register device: %d\n", major_num);
91-
return major_num;
92-
} else {
93-
printk(KERN_INFO "lkm_example module loaded with device major number %d\n", major_num);
94-
return 0;
95-
}
96-
}
97-
98-
static void __exit lkm_example_exit(void) {
99-
/* Remember: we have to clean up after ourselves. Unregister the character device. */
100-
unregister_chrdev(major_num, DEVICE_NAME);
101-
printk(KERN_INFO "Goodbye, World!\n");
102-
}
103-
/* Register module functions */
104-
module_init(lkm_example_init);
105-
module_exit(lkm_example_exit);
1+
#include <linux/init.h>
2+
#include <linux/module.h>
3+
#include <linux/kernel.h>
4+
#include <linux/fs.h>
5+
#include <asm/uaccess.h>
6+
MODULE_LICENSE("GPL");
7+
MODULE_AUTHOR("P Srinivas Rao");
8+
MODULE_DESCRIPTION("A simple Linux loadable Kernel Module.");
9+
MODULE_VERSION("0.01");
10+
11+
#define DEVICE_NAME "lkm_example"
12+
#define EXAMPLE_MSG "Hello, World!\n"
13+
#define MSG_BUFFER_LEN 15
14+
15+
/* Prototypes for device functions */
16+
static int device_open(struct inode *, struct file *);
17+
static int device_release(struct inode *, struct file *);
18+
static ssize_t device_read(struct file *, char *, size_t, loff_t *);
19+
static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
20+
static int major_num;
21+
static int device_open_count = 0;
22+
static char msg_buffer[MSG_BUFFER_LEN];
23+
static char *msg_ptr;
24+
25+
/* This structure points to all of the device functions */
26+
static struct file_operations file_ops = {
27+
.owner = THIS_MODULE,
28+
.read = device_read,
29+
.write = device_write,
30+
.open = device_open,
31+
.release = device_release
32+
};
33+
34+
/* When a process reads from our device, this gets called. */
35+
static ssize_t device_read(struct file *filep, char *buffer, size_t len, loff_t *offset) {
36+
int bytes_read = 0;
37+
/* If we're at the end, loop back to the beginning */
38+
if (*msg_ptr == 0) {
39+
msg_ptr = msg_buffer;
40+
}
41+
42+
/* Put data in the buffer */
43+
while (len && *msg_ptr) {
44+
/* Buffer is in user data, not kernel, so you can't just reference
45+
* with a pointer. The function put_user handles this for us */
46+
put_user(*(msg_ptr++), buffer++);
47+
len--;
48+
bytes_read++;
49+
}
50+
return bytes_read;
51+
}
52+
53+
/* Called when a process tries to write to our device */
54+
static ssize_t device_write(struct file *filep, const char *buffer, size_t len, loff_t *offset) {
55+
/* This is a read-only device */
56+
printk(KERN_ALERT "This operation is not supported.\n");
57+
return -EINVAL;
58+
}
59+
60+
/* Called when a process opens our device */
61+
static int device_open(struct inode *inode, struct file *file) {
62+
/* If device is open, return busy */
63+
if (device_open_count) {
64+
return -EBUSY;
65+
}
66+
device_open_count++;
67+
try_module_get(THIS_MODULE);
68+
return 0;
69+
}
70+
71+
/* Called when a process closes our device */
72+
static int device_release(struct inode *inode, struct file *file) {
73+
/* Decrement the open counter and usage count. Without this, the module would not unload. */
74+
device_open_count--;
75+
module_put(THIS_MODULE);
76+
return 0;
77+
}
78+
79+
static int __init lkm_example_init(void) {
80+
/* Fill buffer with our message */
81+
strncpy(msg_buffer, EXAMPLE_MSG, MSG_BUFFER_LEN);
82+
83+
/* Set the msg_ptr to the buffer */
84+
msg_ptr = msg_buffer;
85+
86+
/* Try to register character device */
87+
major_num = register_chrdev(0, "lkm_example", &file_ops);
88+
89+
if (major_num < 0) {
90+
printk(KERN_ALERT "Could not register device: %d\n", major_num);
91+
return major_num;
92+
} else {
93+
printk(KERN_INFO "lkm_example module loaded with device major number %d\n", major_num);
94+
return 0;
95+
}
96+
}
97+
98+
static void __exit lkm_example_exit(void) {
99+
/* Remember: we have to clean up after ourselves. Unregister the character device. */
100+
unregister_chrdev(major_num, DEVICE_NAME);
101+
printk(KERN_INFO "Goodbye, World!\n");
102+
}
103+
/* Register module functions */
104+
module_init(lkm_example_init);
105+
module_exit(lkm_example_exit);

0 commit comments

Comments
 (0)