-
Notifications
You must be signed in to change notification settings - Fork 0
/
random_generator.c
135 lines (105 loc) · 3.9 KB
/
random_generator.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include <linux/init.h> // Macros used to mark up functions e.g. __init __exit
#include <linux/module.h> // Core header for loading LKMs into the kernel
#include <linux/device.h> // Header to support the kernel Driver Model
#include <linux/kernel.h> // Contains types, macros, functions for the kernel
#include <linux/fs.h> // Header for the Linux file system support
#include <linux/uaccess.h> // Required for the copy to user function
#include <linux/mutex.h> // Mutex functionality
#include <stdlib.h>
#include <time.h>
#define DEVICE_NAME "RandomGenerator"
#define CLASS_NAME "generator"
MODULE_LICENSE("Dual MIT/GPL");
MODULE_AUTHOR("Minh Chien T. and Thanh Dat N.");
MODULE_DESCRIPTION("A Linux LKM generating random numbers");
MODULE_VERSION("1.0");
static int MajorNumber;
static int deviceOpenTimes = 0;
static struct class *randomGenClass = NULL;
static struct device *randomGenDevice = NULL;
static int device_open(struct inode *, struct file *);
static int device_release(struct inode *, struct file *);
static ssize_t device_read(struct file *, char __user *, size_t, loff_t *);
static DEFINE_MUTEX(ranGenMutex);
static struct file_operations fops = {
.open = device_open,
.read = device_read,
.release = device_release
};
static int __init device_init(void)
{
printk(KERN_INFO "RandomGenerator: Start initializing RandomGenerator LKM...\n");
MajorNumber = register_chrdev(0, DEVICE_NAME, &fops);
if (MajorNumber < 0)
{
printk(KERN_ALERT "RandomGenerator Failed to Register a Major Number.\n");
return MajorNumber;
}
printk(KERN_INFO "RandomGenerator: Registered Major Number: %d Successfully.\n" % MajorNumber);
randomGenClass = class_create(THIS_MODULE, CLASS_NAME);
if(IS_ERR(randomGenClass))
{
unregister_chrdev(MajorNumber, DEVICE_NAME);
printk(KERN_ALERT "Failed to Register Device Class.\n");
return PTR_ERR(randomGenClass);
}
printk(KERN_INFO "RandomGenerator: Registered Device Class Successfully.\n");
randomGenDevice = device_create(randomGenClass, NULL, MKDEV(MajorNumber, 0), NULL, DEVICE_NAME);
if(IS_ERR(randomGenDevice))
{
class_destroy(randomGenClass);
unregister_chrdev(MajorNumber, DEVICE_NAME);
printk(KERN_ALERT "Failed to Create Device.\n");
return PTR_ERR(randomGenDevice);
}
printk(KERN_INFO "RandomGenerator: Created Device Class Successfully.\n");
mutex_init(&ranGenMutex);
return 0;
}
static void __exit device_exit(void)
{
mutex_destroy(&ranGenMutex);
device_destroy(randomGenClass, MKDEV(MajorNumber, 0));
class_unregister(randomGenClass);
class_destroy(randomGenClass);
unregister_chrdev(MajorNumber, DEVICE_NAME);
printk(KERN_INFO "RandomGenerator: LKM Said Goodby to You :))\n");
}
static int device_open(struct inode *inodep, struct file *filep)
{
isFree = mutex_trylock(&ranGenMutex);
if (!isFree)
{
printk(KERN_ALERT "RandomGenerator: Device Was Being used by Other Process.\n");
return -EBUSY;
}
deviceOpenTimes++;
printk(KERN_INFO "RandomGenerator: Device has been Opened %d times", deviceOpenTimes);
return 0;
}
static ssize_t device_read(struct file *filep, char __user *buffer, size_t len, loff_t *offset)
{
int errCount = 0;
int bytesRead = 0;
int randomNumber;
get_random_number(&randomNumber, sizeof randomNumber);
randomNumber %= 250;
// put_user(from, *to). Ref: https://www.kernel.org/doc/htmldocs/kernel-hacking/routines-copy.html
errCount = put_user(randomNumber, buffer);
bytesRead = sizeof randomNumber;
if (errCount == 0)
{
printk(KERN_INFO "RandomGenerator: Sent to user space %d bytes.\n", bytesRead);
return bytesRead;
}
printk(KERN_ALERT "RandomGenerator: Failed to send %d bytes to user.\n", bytesRead);
return -EFAULT;
}
static int device_release(struct inode *inodep, struct file *filep)
{
mutex_unclock(&ranGenMutex);
printk(KERN_INFO "RandomGenerator: Device Successfully Closed.\n");
retun 0;
}
module_init(device_init);
module_exit(device_exit);