Skip to content
Snippets Groups Projects
Commit b68650a7 authored by David Maul's avatar David Maul :crab:
Browse files

feat: improve linux module and add message module

parent a48dd837
Branches
No related tags found
No related merge requests found
......@@ -15,6 +15,7 @@ modules.order
# IDE
.idea/
.vscode/
.cache/
*.swp
*~
......
add_subdirectory(cpu_temp)
add_subdirectory(test)
add_executable(test
src/test.c
)
target_link_libraries(test
PRIVATE common
)
target_include_directories(test
PRIVATE include
)
#include <stdio.h>
#include "../../../common/include/communication.h"
#define PATH "/dev/amogus"
int main(int argc, char* argv[]) {
communication_handle_t handle;
if(create_communication_handle(PATH, &handle) != 0) {
printf("Couldn't create communication handle, did you sudo\n");
return 0;
}
printf("Created communication handle\n");
message_t message;
uint32_t data = 69;
if(create_message(&message, 0, sizeof(uint32_t),UINT32, &data) != 0) {
printf("Couldn't create message\n");
return 0;
}
printf("Created message\n");
if(push_message(&handle, &message) != 0) {
printf("Couldn't push message\n");
return 0;
}
printf("Destroyed message\n");
destroy_communication_handle(&handle);
printf("Destroyed communication handle\n");
}
add_library(common
src/protocol.c
src/communication.c
)
target_include_directories(common
PUBLIC include
......
#pragma once
#include <stddef.h>
#include <stdint.h>
#include "message.h"
typedef struct communication_handle {
int fd;
} communication_handle_t;
int create_communication_handle(char* path, communication_handle_t* handle);
void destroy_communication_handle(communication_handle_t* handle);
int create_message(message_t* message, int32_t id, message_data_type_t type, size_t length, void* data);
int push_message(communication_handle_t* handle, message_t* message);
void destroy_message(message_t* message);
#pragma once
#if defined(__KERNEL__)
#include <linux/types.h>
typedef u8 uint8_t;
typedef u16 uint16_t;
typedef u32 uint32_t;
typedef u64 uint64_t;
typedef s8 int8_t;
typedef s16 int16_t;
typedef s32 int32_t;
typedef s64 int64_t;
#else
#include <stdint.h>
#include <stddef.h>
#endif
#define MESSAGE_DATA_SIZE 4096
typedef enum message_data_type : uint32_t {
INT8,
UINT8,
INT16,
UINT16,
INT32,
UINT32,
INT64,
UINT64,
FLOAT32,
FLOAT64
} message_data_type_t;
typedef struct message {
int32_t id;
message_data_type_t type;
uint32_t length;
uint8_t data[MESSAGE_DATA_SIZE];
} message_t;
size_t message_data_type_size(message_data_type_t type);
#include <stddef.h>
#include "protocol.h"
void *create_shmem_region(daemon_measurement_datatype_t datatype, size_t length);
int destroy_shmem_region(void *region);
#include "../include/communication.h"
#include <stddef.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int create_communication_handle(char* path, communication_handle_t* handle) {
handle->fd = open(path, O_WRONLY);
if (handle->fd < 0) {
return -1;
}
return 0;
}
void destroy_communication_handle(communication_handle_t* handle) {
close(handle->fd);
}
int create_message(message_t* message, int32_t id, message_data_type_t type, size_t length, void* data) {
message->id = id;
message->type = type;
message->length = length;
if(length > MESSAGE_DATA_SIZE) {
return -1;
}
memcpy(&message->data, data, length);
return 0;
}
int push_message(communication_handle_t* handle, message_t* message) {
if(write(handle->fd, message, sizeof(message_t)) == -1) {
return -1;
}
return 0;
}
#include "../include/message.h"
size_t message_data_type_size(message_data_type_t type) {
switch(type) {
case INT8:
return sizeof(int8_t);
case UINT8:
return sizeof(uint8_t);
case INT16:
return sizeof(int16_t);
case UINT16:
return sizeof(uint16_t);
case INT32:
return sizeof(int32_t);
case UINT32:
return sizeof(uint32_t);
case INT64:
return sizeof(int64_t);
case UINT64:
return sizeof(uint64_t);
case FLOAT32:
return sizeof(float);
case FLOAT64:
return sizeof(double);
default:
return 0;
}
}
#include "protocol.h"
#include <stddef.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
void *create_shmem_region(daemon_measurement_datatype_t datatype, size_t length)
{
int fd = open("/dev/sibyl", O_RDWR);
if (fd < 0)
{
perror("open");
return NULL;
}
void *ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (ptr == MAP_FAILED)
{
perror("mmap");
return NULL;
}
return ptr;
}
int destroy_shmem_region(void *region)
{
return 0;
}
\ No newline at end of file
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <linux/ktime.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/vmalloc.h>
#include <linux/uaccess.h>
#include "../common/include/message.h"
// Device name
#define DEVICE_NAME "sibyl"
#define DEVICE_NAME "amogus"
#define CLASS_NAME "amogus_class"
static int major_number;
static struct class *shm_class;
static struct cdev shm_cdev;
static void *shm_buffer;
static struct class* class = NULL;
static struct cdev mycdev;
// Max number entries
#define MAX_ENTRIES 512
// Max size of entries in bytes
#define MAX_ENTRY_SIZE 4096
static message_t* message;
typedef struct entry
{
bool ready;
void *buffer;
size_t length;
} entry_t;
static entry_t *entries;
static size_t num_entries;
// Kernel thread
static struct task_struct *kthread;
// File operations
static int shm_open(struct inode *inode, struct file *file)
static int device_open(struct inode *inode, struct file *file)
{
return 0;
}
static int shm_release(struct inode *inode, struct file *file)
static int device_release(struct inode *inode, struct file *file)
{
return 0;
}
static int shm_mmap(struct file *file, struct vm_area_struct *vma)
{
unsigned long size = vma->vm_end - vma->vm_start;
void *buffer;
if (size > MAX_ENTRY_SIZE || num_entries >= MAX_ENTRIES)
return -EINVAL;
// Allokiere Speicher für den Buffer
buffer = kmalloc(size, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
// Erstelle neuen Entry
entries[num_entries].buffer = buffer;
entries[num_entries].length = size;
entries[num_entries].ready = false;
// Mappe den neuen Buffer
unsigned long pfn = virt_to_phys(buffer) >> PAGE_SHIFT;
vm_flags_set(vma, VM_IO);
vm_flags_set(vma, VM_DONTEXPAND | VM_DONTDUMP);
if (remap_pfn_range(vma, vma->vm_start, pfn, size, vma->vm_page_prot))
static ssize_t device_write(struct file *filp, const char *input,
size_t length, loff_t *offset)
{
kfree(buffer);
return -EAGAIN;
if(length != sizeof(message_t)) {
printk(KERN_ALERT "lkm: Tried to to write more bytes than allowed\n");
return -EFAULT;
}
num_entries++;
return 0;
if (copy_from_user((void*)message, input, length)) {
return -EFAULT;
}
static const struct file_operations shm_fops = {
.owner = THIS_MODULE,
.open = shm_open,
.release = shm_release,
.mmap = shm_mmap,
};
printk(KERN_INFO "lkm: received write of size %zu\n",length);
static int thread(void *data)
{
while (!kthread_should_stop())
{
u64 ms = ktime_get_real_ns() / 1000000;
printk(KERN_INFO "[%llu]:\n", ms);
for (int n = 0; n < num_entries; n++)
{
printk(KERN_INFO "\t- %d: %d\n", n, ((int *)(entries[n].buffer))[0]);
}
ssleep(1); // 1 Sekunde schlafen
}
return 0;
return length;
}
static const struct file_operations fops = {
.write = device_write,
.open = device_open,
.release = device_release
};
static int __init lkm_init(void)
{
// Initialize entries
num_entries = 0;
entries = (entry_t *)kmalloc(sizeof(entry_t) * MAX_ENTRIES, GFP_KERNEL);
dev_t dev;
if (!entries)
{
printk(KERN_ERR "Failed to allocate memory\n");
return -ENOMEM;
}
message = (message_t*)vmalloc(sizeof(message_t));
int err;
dev_t dev;
if(message == NULL) {
return -1;
}
err = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME);
if (err)
{
printk(KERN_ERR "Failed to allocate char device region\n");
kfree(shm_buffer);
return err;
// Dynamically allocate major number
if (alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME) < 0) {
vfree(message);
printk(KERN_ALERT "Failed to allocate major number\n");
return -1;
}
major_number = MAJOR(dev);
shm_class = class_create(DEVICE_NAME);
if (IS_ERR(shm_class))
{
printk(KERN_ERR "Failed to create device class\n");
unregister_chrdev_region(dev, 1);
kfree(shm_buffer);
return PTR_ERR(shm_class);
class = class_create(CLASS_NAME);
if (IS_ERR(class)) {
vfree(message);
unregister_chrdev_region(MKDEV(major_number, 0), 1);
printk(KERN_ALERT "Failed to create device class\n");
return PTR_ERR(class);
}
if (device_create(shm_class, NULL, dev, NULL, DEVICE_NAME) == NULL)
{
printk(KERN_ERR "Failed to create device\n");
class_destroy(shm_class);
unregister_chrdev_region(dev, 1);
kfree(shm_buffer);
return -EINVAL;
if (device_create(class, NULL, MKDEV(major_number, 0), NULL, DEVICE_NAME) == NULL) {
vfree(message);
class_destroy(class);
unregister_chrdev_region(MKDEV(major_number, 0), 1);
printk(KERN_ALERT "Failed to create device\n");
return -1;
}
cdev_init(&shm_cdev, &shm_fops);
err = cdev_add(&shm_cdev, dev, 1);
if (err)
{
printk(KERN_ERR "Failed to add char device\n");
device_destroy(shm_class, dev);
class_destroy(shm_class);
unregister_chrdev_region(dev, 1);
kfree(shm_buffer);
return err;
cdev_init(&mycdev, &fops);
if (cdev_add(&mycdev, MKDEV(major_number, 0), 1) < 0) {
vfree(message);
device_destroy(class, MKDEV(major_number, 0));
class_destroy(class);
unregister_chrdev_region(MKDEV(major_number, 0), 1);
printk(KERN_ALERT "Failed to add character device\n");
return -1;
}
printk(KERN_INFO "SHM device initialized\n");
kthread = kthread_run(thread, NULL, "kthread");
return PTR_ERR_OR_ZERO(kthread);
printk(KERN_INFO, "Kernel thread started\n");
printk(KERN_INFO "lkm: device created successfully\n");
return 0;
}
static void __exit lkm_exit(void)
{
dev_t dev = MKDEV(major_number, 0);
cdev_del(&shm_cdev);
device_destroy(shm_class, dev);
class_destroy(shm_class);
unregister_chrdev_region(dev, 1);
kfree(shm_buffer);
printk(KERN_INFO "SHM device removed\n");
kthread_stop(kthread);
printk(KERN_INFO, "Kernel thread stopped\n");
for (size_t i = 0; i < num_entries; i++)
{
kfree(entries[i].buffer);
}
kfree(entries);
vfree(message);
cdev_del(&mycdev);
device_destroy(class, MKDEV(major_number, 0));
class_destroy(class);
unregister_chrdev_region(MKDEV(major_number, 0), 1);
printk(KERN_INFO "lkm: device removed successfully\n");
}
module_init(lkm_init);
module_exit(lkm_exit);
MODULE_LICENSE("GPL");
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment