I am writing a kernel module, that when written to will allocate kernel memory, but as of now does nothing when read from, here is what I got so far, but it locks up my system when I run this command "echo "hello there" > /dev/testdev"
Code:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/devfs_fs_kernel.h>
#define DATA_SIZE 256
/* Add semaphore support. */
int device_open(struct inode *inode, struct file *filp);
int device_release(struct inode *inode, struct file *filp);
ssize_t device_read(struct file *filp, char *buf, size_t count, loff_t *pos);
ssize_t device_write(struct file *filp, const char *buf, size_t count, loff_t *pos);
static int major;
static struct file_operations fops = {
.open = device_open,
.release = device_release,
.read = device_read,
.write = device_write
};
static struct device_data {
char data[DATA_SIZE];
struct device_data *next;
};
static struct device_data *first;
static struct device_data *wkdata;
int device_open(struct inode *inode, struct file *filp) {
MOD_INC_USE_COUNT;
return 0;
}
int device_release(struct inode *inode, struct file *filp) {
MOD_DEC_USE_COUNT;
return 0;
}
ssize_t device_read(struct file *filp, char *buf, size_t count, loff_t *pos) {
return 0;
}
ssize_t device_write(struct file *filp, const char *buf, size_t count, loff_t *pos) {
wkdata = first;
while(1) {
if(wkdata == (struct device_data *)NULL)
return -1;
while(count > DATA_SIZE) {
printk("\nbefore memcpy.\n");
memcpy(wkdata->data, buf, DATA_SIZE);
printk("After memcpy.\n");
count-=DATA_SIZE;
wkdata->next = (struct device_data *)kmalloc(sizeof(struct device_data), GFP_KERNEL);
wkdata = wkdata->next;
}
if(count > 0) {
wkdata->next = (struct device_data *)kmalloc(sizeof(struct device_data), GFP_KERNEL);
wkdata = wkdata->next;
memcpy(wkdata->data, buf, count);
}
}
return 0;
}
static __init int device_init(void) {
major = register_chrdev(0, "testdev", &fops);
devfs_register(NULL, "testdev", DEVFS_FL_AUTO_DEVNUM, 0, 0, S_IFCHR | S_IRUGO | S_IWUGO, &fops, 0);
first = (struct device_data *)kmalloc(sizeof(struct device_data), GFP_KERNEL);
return 0;
}
static __exit void device_exit(void) {
}
module_init(device_init);
module_exit(device_exit);
MODULE_LICENSE("GPL");