Skip to content
Snippets Groups Projects
Unverified Commit 2ff1efc3 authored by CyberKatze2077's avatar CyberKatze2077 Committed by GitHub
Browse files

Merge branch 'main' into addingScalability

parents 4b2684d5 b3707fdb
No related branches found
No related tags found
1 merge request!2Adding scalability
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
#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);
...@@ -25,7 +25,7 @@ static void read_cpu_freq_and_write(int fd) ...@@ -25,7 +25,7 @@ static void read_cpu_freq_and_write(int fd)
char message[128]; char message[128];
snprintf(message, sizeof(message), "%.3f", freq); 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) { if (written < 0) {
perror("write to pipeTwo"); perror("write to pipeTwo");
} else { } else {
......
...@@ -27,7 +27,7 @@ static void read_cpu_temp_and_write(int fd) ...@@ -27,7 +27,7 @@ static void read_cpu_temp_and_write(int fd)
// Schreiben, aber NICHT den FD schließen. // Schreiben, aber NICHT den FD schließen.
// Nur so viele Bytes schreiben, wie tatsächlich gebraucht werden. // 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) { if (written < 0) {
perror("write to pipeOne"); perror("write to pipeOne");
} else { } else {
......
#!/bin/bash #!/bin/bash
#Prozesse starten
/usr/local/bin/cpu_temp & /usr/local/bin/cpu_temp &
/usr/local/bin/cpu_freq & /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 while true
do do
sleep 3600 sleep 3600
......
No preview for this file type
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#include <fcntl.h> #include <fcntl.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <zlib.h>
#define MAX_PROCESSES 10 #define MAX_PROCESSES 10
#define PIPE_DIR "/tmp/" //name von pipe ist jetzt gleich name von process #define PIPE_DIR "/tmp/" //name von pipe ist jetzt gleich name von process
...@@ -113,111 +115,3 @@ int main() { ...@@ -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
[Unit] [Unit]
Description=Monitoring Processes Description=Monitoring Processes and sending to character device
After=network.target After=network.target
[Service] [Service]
Type=simple Type=simple
ExecStart=/usr/local/bin/process_monitoring.sh ExecStart=/usr/local/bin/process_monitoring.sh /tmp/cpu_temp /tmp/cpu_freq
Restart=always Restart=always
[Install] [Install]
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment