diff --git a/Kernel/Makefile b/Kernel/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..bf36e7f57193878db21d084a61da47abe669c9a5 --- /dev/null +++ b/Kernel/Makefile @@ -0,0 +1,7 @@ +obj-m := kernel_M.o +KVERSION = $(shell uname -r) +all: + make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules + +clean: + make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean \ No newline at end of file diff --git a/Kernel/kernel_M.c b/Kernel/kernel_M.c new file mode 100644 index 0000000000000000000000000000000000000000..484766e8501e7694a9fb9df849fac08d45a2e008 --- /dev/null +++ b/Kernel/kernel_M.c @@ -0,0 +1,277 @@ +#include <linux/init.h> +#include <linux/module.h> + +#include <linux/kernel.h> +#include <linux/fs.h> // For file_operations +#include <linux/uaccess.h> // For copy_from_user +#include <linux/cdev.h> // For cdev +#include <linux/device.h> // For device_create, class_create +#include <linux/slab.h> // For kmalloc, kfree + +#include <linux/crc32.h> // Include CRC32 + +#include <linux/gpio.h> // GPIO support +#include <linux/delay.h> // Delay functions +#include <linux/jiffies.h> // Time measurement + +#include <linux/kthread.h> // Kernel threads +#include <linux/sched.h> // Task scheduling + +#define DEVICE_NAME "packet_receiver" +#define CLASS_NAME "packet_class" + +// cat /sys/kernel/debug/gpio +#define GPIO_DATA 17 // GPIO for data transmission +#define GPIO_CLOCK 27 // GPIO for clock control + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Me :)"); +MODULE_DESCRIPTION("A kernel module to receive packets from userspace."); +MODULE_VERSION("1.7"); + +// The size of the receive buffer +#define RECV_BUF_SIZE 512 + +// Global variables for device number, class, device. +static dev_t dev_number; +static struct class *packet_class = NULL; +static struct cdev packet_cdev; + +// Store last valid data packet +static char last_valid_packet[256] = {0}; + +// Time of last transmission +static struct task_struct *transmit_thread; + +// Flag to control loop in the thread +static int keep_sending = 0; + +// This buffer will temporarily store data from userspace +static char *recv_buffer; + +// Forward declarations for file operations +static int packet_open(struct inode *inode, struct file *file); //not used +static int packet_release(struct inode *inode, struct file *file); //not used +static ssize_t packet_read(struct file *filp, char __user *buf, size_t len, loff_t *offset); //not used +static ssize_t packet_write(struct file *filp, const char __user *buf, size_t len, loff_t *offset); +static unsigned long calculate_crc32(const char *data, size_t len); +static int transmit_loop(void *data); // Kernel thread function + +// File operations structure +static struct file_operations fops = { + .owner = THIS_MODULE, + .open = packet_open, //not used + .read = packet_read, //not used + .write = packet_write, + .release = packet_release, //not used +}; + +// CRC32 Calculation Function +// uses the same polynomial as zlib’s standard CRC32 +static u32 calculate_crc32(const char *data, size_t len) { + return crc32(0, data, len); +} + +// ====================== Device Open ====================== +static int packet_open(struct inode *inode, struct file *file) { + printk(KERN_INFO "packet_receiver: Device opened.\n"); + return 0; +} + +// ====================== Kernel Thread for Continuous Sending ====================== +static int transmit_loop(void *data) { + while (!kthread_should_stop()) { + if (keep_sending && strlen(last_valid_packet) > 0) { + // Wait for clock signal + if (gpio_get_value(GPIO_CLOCK) == 1) { + printk(KERN_INFO "packet_receiver: Clock HIGH -> Pausing transmission.\n"); + msleep(100); // Small sleep to avoid busy looping + continue; + } + + // Transmit the last valid packet + for (size_t i = 0; i < strlen(last_valid_packet); i++) { + gpio_set_value(GPIO_DATA, 1); + msleep(1); + gpio_set_value(GPIO_DATA, 0); + msleep(1); + } + + printk(KERN_INFO "packet_receiver: Sent data to GPIO %d\n", GPIO_DATA); + + // Wait 3x the transmission time before sending again + msleep(strlen(last_valid_packet) * 3); + } else { + msleep(100); // Wait if no valid packet + } + } + return 0; +} + +// ====================== Device Read ====================== +static ssize_t packet_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) { + printk(KERN_INFO "packet_receiver: Read called.\n"); + return 0; +} + +// ====================== Device Write ====================== +static ssize_t packet_write(struct file *filp, const char __user *buf, size_t len, loff_t *offset) { + // Bound the incoming size to the size of the buffer + size_t to_copy = min(len, (size_t)RECV_BUF_SIZE - 1); + + // Clear the buffer before copying data into it (for safety) + memset(recv_buffer, 0, RECV_BUF_SIZE); + + // Copy data from user space into recv_buffer + if (copy_from_user(recv_buffer, buf, to_copy) != 0) { + printk(KERN_ERR "packet_receiver: copy_from_user failed.\n"); + return -EFAULT; + } + + // Ensure null-termination + recv_buffer[to_copy] = '\0'; + + unsigned int sender_hex = 0; + int value_id_0 = -1, value_id_1 = -1; + char value_str_0[64] = {0}; + char value_str_1[64] = {0}; + unsigned long crc_val = 0; + + printk(KERN_INFO "packet_receiver: Parsed fields [matches=%d]:\n", matches); + printk(KERN_INFO " sender=0x%X\n", sender_hex); + printk(KERN_INFO " value_id_0=%d value_0=\"%s\"\n", value_id_0, value_str_0); + printk(KERN_INFO " value_id_1=%d value_1=\"%s\"\n", value_id_1, value_str_1); + printk(KERN_INFO " crc=0x%lX\n", crc_val); + + // Prepare the payload for CRC verification + char crc_buffer[256]; + snprintf(crc_buffer, sizeof(crc_buffer), "SENDER=0x%x VALUE_ID=%d VALUE=%s VALUE_ID=%d VALUE=%s", + sender_hex, value_id_0, value_str_0, value_id_1, value_str_1); + + // Calculate CRC32 for the received data excluding the CRC field + unsigned long computed_crc = calculate_crc32(crc_buffer, strlen(crc_buffer)); + printk(KERN_INFO " computed_crc=0x%lX\n", computed_crc); + + // Check CRC32 before transmission + if (computed_crc != crc_val) { + printk(KERN_ERR "packet_receiver: CRC32 mismatch! Data rejected.\n"); + return -EIO; + } + + // Store the valid packet + strcpy(last_valid_packet, crc_buffer); + keep_sending = 1; + + printk(KERN_INFO "packet_receiver: Sent data to GPIO %d\n", GPIO_DATA); + + // Return the number of bytes written + return len; +} + +// ====================== Device Release ====================== +static int packet_release(struct inode *inode, struct file *file) { + printk(KERN_INFO "packet_receiver: Device closed.\n"); + return 0; +} + +// ====================== Module Init ====================== +static int __init packet_init(void) { + int ret; + + // Allocate a device number dynamically + ret = alloc_chrdev_region(&dev_number, 0, 1, DEVICE_NAME); + if (ret < 0) { + printk(KERN_ERR "packet_receiver: Failed to allocate major/minor.\n"); + return ret; + } + printk(KERN_INFO "packet_receiver: Registered with major=%d, minor=%d\n", + MAJOR(dev_number), MINOR(dev_number)); + + // Initialize the cdev structure + cdev_init(&packet_cdev, &fops); + packet_cdev.owner = THIS_MODULE; + + // Add the cdev to the kernel + ret = cdev_add(&packet_cdev, dev_number, 1); + if (ret < 0) { + printk(KERN_ERR "packet_receiver: Unable to add cdev.\n"); + unregister_chrdev_region(dev_number, 1); + return ret; + } + + // Create a class for udev + packet_class = class_create(CLASS_NAME); + if (IS_ERR(packet_class)) { + printk(KERN_ERR "packet_receiver: Failed to create class.\n"); + cdev_del(&packet_cdev); + unregister_chrdev_region(dev_number, 1); + return PTR_ERR(packet_class); + } + + // Create a device node /dev/packet_receiver + if (IS_ERR(device_create(packet_class, NULL, dev_number, NULL, DEVICE_NAME))) { + printk(KERN_ERR "packet_receiver: Failed to create device.\n"); + class_destroy(packet_class); + cdev_del(&packet_cdev); + unregister_chrdev_region(dev_number, 1); + return -1; + } + + // Allocate memory for receive buffer + recv_buffer = kmalloc(RECV_BUF_SIZE, GFP_KERNEL); + if (!recv_buffer) { + printk(KERN_ERR "packet_receiver: Failed to allocate recv_buffer.\n"); + device_destroy(packet_class, dev_number); + class_destroy(packet_class); + cdev_del(&packet_cdev); + unregister_chrdev_region(dev_number, 1); + return -ENOMEM; + } + + gpio_request(GPIO_DATA, "packet_data"); + gpio_request(GPIO_CLOCK, "packet_clock"); + gpio_direction_output(GPIO_DATA, 0); + gpio_direction_input(GPIO_CLOCK); // Clock is an input signal + + // Start the transmission thread + transmit_thread = kthread_run(transmit_loop, NULL, "packet_transmitter"); + if (IS_ERR(transmit_thread)) { + printk(KERN_ERR "packet_receiver: Failed to create transmit_thread.\n"); + kfree(recv_buffer); + device_destroy(packet_class, dev_number); + class_destroy(packet_class); + cdev_del(&packet_cdev); + unregister_chrdev_region(dev_number, 1); + return PTR_ERR(transmit_thread); + } + + printk(KERN_INFO "packet_receiver: Module loaded.\n"); + return 0; +} + +// ====================== Module Exit ====================== +static void __exit packet_exit(void) { + + // Stop the transmission thread + kthread_stop(transmit_thread); + + // Free recv_buffer + kfree(recv_buffer); + + // Remove device node + device_destroy(packet_class, dev_number); + // Destroy class + class_destroy(packet_class); + // Delete cdev + cdev_del(&packet_cdev); + // Free device numbers + unregister_chrdev_region(dev_number, 1); + // Free GPIOs + gpio_free(GPIO_DATA); + gpio_free(GPIO_CLOCK); + + printk(KERN_INFO "packet_receiver: Module unloaded.\n"); +} + +module_init(packet_init); +module_exit(packet_exit); diff --git a/Processes/cpu_freq.c b/Processes/cpu_freq.c index 31b707c936a089b1f1ffdce80998ca055e655603..c81b4a090a8767ec9c35656e52a6890ceebc1c01 100644 --- a/Processes/cpu_freq.c +++ b/Processes/cpu_freq.c @@ -25,7 +25,7 @@ static void read_cpu_freq_and_write(int fd) char message[128]; snprintf(message, sizeof(message), "%.3f", freq); - ssize_t written = write(fd, message, strlen(message) + 1); + ssize_t written = write(fd, message, strlen(message)); if (written < 0) { perror("write to pipeTwo"); } else { diff --git a/Processes/cpu_temp.c b/Processes/cpu_temp.c index 16aabd01a36475b3cbff92df5a51482278edaebb..5ec6e84e3a0030918ea0af3b6b162a1a1b460fc8 100644 --- a/Processes/cpu_temp.c +++ b/Processes/cpu_temp.c @@ -27,7 +27,7 @@ static void read_cpu_temp_and_write(int fd) // Schreiben, aber NICHT den FD schließen. // Nur so viele Bytes schreiben, wie tatsächlich gebraucht werden. - ssize_t written = write(fd, message, strlen(message) + 1); + ssize_t written = write(fd, message, strlen(message)); if (written < 0) { perror("write to pipeOne"); } else { diff --git a/Processes/process_monitoring.sh b/Processes/process_monitoring.sh index a8b758862ca9030a509c905f4e17ec592e689710..47848e8fb16942342cd25e829702b178cf5f7b5d 100644 --- a/Processes/process_monitoring.sh +++ b/Processes/process_monitoring.sh @@ -1,8 +1,15 @@ #!/bin/bash +#Prozesse starten /usr/local/bin/cpu_temp & /usr/local/bin/cpu_freq & +sleep 200 + +# Gleiche Argumente in die main übergeben +/usr/local/bin/main "$@" + +# Damit das Skript nicht sofort beendet, bleibst du in einer Endlosschleife while true do sleep 3600 diff --git a/main b/main index 98261929dd7adb1a4010b1d036332b20244b822a..9b5e3faf7da65f04e5d1a3cfde69861fbd95f710 100755 Binary files a/main and b/main differ diff --git a/main.c b/main.c index 5d0d3590e9486bf2ceee38524080e3600675dd48..2b84f49883e0b39ee70ca67631fea24646800e32 100644 --- a/main.c +++ b/main.c @@ -5,6 +5,8 @@ #include <fcntl.h> #include <string.h> #include <errno.h> +#include <zlib.h> + #define MAX_PROCESSES 10 #define PIPE_DIR "/tmp/" //name von pipe ist jetzt gleich name von process @@ -113,111 +115,3 @@ int main() { } -//alter code: -/* - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <string.h> -#include <errno.h> - -static const char *PIPE_ONE = "/tmp/pipeOne"; -static const char *PIPE_TWO = "/tmp/pipeTwo"; - -int main(void) -{ - // mkfifo() nur ausführen, wenn die Pipes noch nicht existieren, - // bzw. Fehler ignorieren, falls schon existiert: - if (mkfifo(PIPE_ONE, 0666) < 0 && errno != EEXIST) { - perror("mkfifo pipeOne"); - return 1; - } - if (mkfifo(PIPE_TWO, 0666) < 0 && errno != EEXIST) { - perror("mkfifo pipeTwo"); - return 1; - } - - // Beide Pipes blockierend öffnen - int fdOne = open(PIPE_ONE, O_RDONLY); - if (fdOne == -1) { - perror("open pipeOne for reading"); - return 1; - } - - int fdTwo = open(PIPE_TWO, O_RDONLY); - if (fdTwo == -1) { - perror("open pipeTwo for reading"); - close(fdOne); - return 1; - } - - // Dauerhafte Lese-Schleife - while (1) { - char bufOne[128] = {0}; - char bufTwo[128] = {0}; - - // =========== Lesevorgang PipeOne =========== - // read() kann blockieren, wenn noch keine Daten da sind, - // da wir blockierendes I/O verwenden. - // Wenn die Schreibseite offen bleibt, kommen periodisch neue Daten. - ssize_t bytesReadOne = read(fdOne, bufOne, sizeof(bufOne)); - if (bytesReadOne > 0) { - // Gültige Daten -> ausgeben - printf("PipeOne CPU Temp: %s °C\n", bufOne); - } else if (bytesReadOne == 0) { - // EOF -> Schreibseite hat geschlossen - // -> ggf. Pipe erneut öffnen - printf("PipeOne closed by writer. Reopening...\n"); - close(fdOne); - - // Neu öffnen - fdOne = open(PIPE_ONE, O_RDONLY); - if (fdOne == -1) { - perror("Reopen pipeOne"); - break; // oder return 1; - } - } else { - // bytesReadOne < 0 => Fehler - if (errno == EINTR) { - // Signal unterbrochen, einfach weiter - continue; - } - perror("read pipeOne"); - break; // oder return 1; - } - - // =========== Lesevorgang PipeTwo =========== - ssize_t bytesReadTwo = read(fdTwo, bufTwo, sizeof(bufTwo)); - if (bytesReadTwo > 0) { - printf("PipeTwo CPU Freq: %s GHz\n", bufTwo); - } else if (bytesReadTwo == 0) { - printf("PipeTwo closed by writer. Reopening...\n"); - close(fdTwo); - fdTwo = open(PIPE_TWO, O_RDONLY); - if (fdTwo == -1) { - perror("Reopen pipeTwo"); - break; - } - } else { - if (errno == EINTR) { - continue; - } - perror("read pipeTwo"); - break; - } - - // Kurze Pause, damit CPU-Last nicht durch - // Dauerschleife hochgetrieben wird - usleep(200000); // 200 ms - } - - // Sollte man jemals aus der while(1)-Schleife ausbrechen: - close(fdOne); - close(fdTwo); - - return 0; -} -*/ \ No newline at end of file diff --git a/process-monitor.service b/process-monitor.service new file mode 100644 index 0000000000000000000000000000000000000000..d09ad71be4f14ca5fc63510e8e56c88f50d65b51 --- /dev/null +++ b/process-monitor.service @@ -0,0 +1,11 @@ +[Unit] +Description=Monitoring Processes and sending to character device +After=network.target + +[Service] +Type=simple +ExecStart=/usr/local/bin/process_monitoring.sh /tmp/cpu_temp /tmp/cpu_freq +Restart=always + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/tracking.service b/tracking.service deleted file mode 100644 index f4c409b19dbaa5dce6eef7b49ba97f7d30ed1e03..0000000000000000000000000000000000000000 --- a/tracking.service +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -Description=Monitoring Processes -After=network.target - -[Service] -Type=simple -ExecStart=/usr/local/bin/process_monitoring.sh -Restart=always - -[Install] -WantedBy=multi-user.target \ No newline at end of file