Building off of this, I would like to change process priorities based on RAM usage. I’m perfectly aware that this isn’t always the best way to change priorities, but this is just for a project. I’m trying to use renice and execvp to set process priorities.
The problem is that I want to launch renice with additional parameters to change the process priority while the program is running. The problem is that when I run execvp with the correct #include it bounces an error with a lot of dependencies.
My main.c has two arrays. One has the process IDs and the other has their corresponding RAM usage and they get sorted in descending order. Is there any way to change process priorities with this information?
main.c
#include </usr/include/asm-generic/unistd.h> //execvp: #include <linux/kernel.h> // printk(), pr_*() #include <linux/module.h> // THIS_MODULE, MODULE_VERSION, ... #include <linux/init.h> // module_{init,exit} #include <linux/sched/task.h> // struct task_struct, {get,put}_task_struct() #include <linux/mm.h> // get_mm_rss() #include <linux/pid.h> // struct pid, get_pid_task(), find_get_pid() #include <linux/moduleparam.h> // module_param_named() #include <linux/slab.h> struct task_struct *task; /* Structure defined in sched.h for tasks/processes */ /* * Power Services: 80-51% * renice -n 5 -p [pid] //(20-5)/20 = 75% of CPU * Standard Services: 50-26% * renice -n 10 -p [pid] //(20-10)/20 = 50% of CPU * Optimized Services: 1-25% * renice -n 15 -p [pid] //(20-15)/20 = 25% of CPU */ /* static char *envp[] = { "SHELL=/bin/bash", "HOME=/bin/admin0", "USER=admin", "PATH=/home/admin/bin:/home/admin/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/admin", "DISPLAY=:0", "PWD=/home/admin", NULL}; */ typedef struct { int *array; size_t used; size_t size; } id_array; typedef struct { unsigned long *array; size_t used; size_t size; } ram_array; int rss = 0; int counter = 0;//Iterator for arrays //Change according to available memory size int highLimit =322122547; //3GB int mediumLimit=214748364;//2GB int lowLimit= 107374182;//1GB //The RAM usage and process ID data types are different and require different argument types void initArray(id_array *a, size_t initialSize); void insertArray(id_array *a, int element); void initarray(ram_array *a, size_t initialSize); void insertarray(ram_array *a, long unsigned element); // Function to swap the the position of two elements void swapper(long unsigned *a, long unsigned *b); void id_swap(int *a, int *b);//Swap IDs when sorting void heapify(unsigned long* arr, int n, int i, int *id); // Main function to do heap sort void heapSort(ram_array *a, id_array *b); id_array pid; ram_array ram; int iterate_init(void) /* Init Module */ { printk(KERN_INFO "%s","LOADING MODULEn"); /* good practice to log when loading/removing modules */ initArray(&pid, 1); initarray(&ram, 1); for_each_process( task ) //Loop through all the processes to count how many there are. This function is located in linuxschedsignal.h { get_task_struct(task); insertArray(&pid, task->pid); if(task->mm) { rss = get_mm_rss(task->mm) << PAGE_SHIFT; insertarray(&ram, rss); } else { insertarray(&ram, 0); } counter++; put_task_struct(task); } counter = 0; heapSort(&ram, &pid); while(counter < ram.used) { printk("Process %i: %lu bytes of RAM, Priority: %in", pid.array[counter], ram.array[counter], counter + 1);//Remember to put a n at the end of each printk call, or your formatting can get messed up. //Modifying Priority Engine if (ram.array[counter] < mediumLimit){ printk("Process %i is a Optimized Process!!n", pid.array[counter]); char param; param= "/usr/bin/renice -n 15 -p " + pid.array[counter]; char *args[3]={"/usr/bin/renice", param, NULL}; execvp("/usr/bin/renice", args); } else if (ram.array[counter] > mediumLimit && ram.array[counter] < highLimit){ printk("Process %i is a Standard Process!!n", pid.array[counter]); //param= "renice -n 10 -p " + pid.array[counter]; //char *args[3]={"renice", param, NULL}; //execvp("renice", args); } else { printk("Process %i is a Power Process!!n", pid.array[counter]); //param= "renice -n 5 -p " + pid.array[counter]; //char *args[3]={"renice", param, NULL}; //execvp("renice", args); } counter++; } return 0; } /* End of Init Module */ // Function to swap the the position of two elements void swapper(long unsigned *a, long unsigned *b) { int temp = *a; *a = *b; *b = temp; } void id_swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } void heapify(unsigned long* arr, int n, int i, int *id) { // Find smallest among root, left child and right child int smallest = i; int left = 2 * i + 1; int right = 2 * i + 2; if (left < n && arr[left] < arr[smallest]) smallest = left; if (right < n && arr[right] < arr[smallest]) smallest = right; // Swap and continue heapifying if root is not largest if (smallest != i) { swapper(&arr[i], &arr[smallest]); id_swap(&id[i], &id[smallest]);//Switch corresponding ID with its RAM usage. heapify(arr, n, smallest, id); } } // Main function to do heap sort void heapSort(ram_array *a, id_array *b) { // Build max heap int i = a->used / 2 - 1; while(i >= 0) { heapify(a->array, a->used, i, b->array); i--; } i = a->used - 1; // Heap sort while(i >= 0) { swapper(&a->array[0], &a->array[i]); id_swap(&b->array[0], &b->array[i]);//Switch corresponding ID with its RAM usage. // Heapify root element to get highest element at root again heapify(a->array, i, 0, b->array); i--; } } void initArray(id_array *a, size_t initialSize) { a->array = kvmalloc(initialSize * sizeof(int), GFP_KERNEL); a->used = 0; a->size = initialSize; } void insertArray(id_array *a, int element) { // a->used is the number of used entries, because a->array[a->used++] updates a->used only *after* the array has been accessed. // Therefore a->used can go up to a->size if (a->used == a->size) { a->size *= 2; a->array = krealloc(a->array, a->size * sizeof(int), GFP_KERNEL); } a->array[a->used++] = element; } void initarray(ram_array *a, size_t initialSize) { a->array = kvmalloc(initialSize * sizeof(unsigned long), GFP_KERNEL); a->used = 0; a->size = initialSize; } void insertarray(ram_array *a, unsigned long element) { // a->used is the number of used entries, because a->array[a->used++] updates a->used only *after* the array has been accessed. // Therefore a->used can go up to a->size if (a->used == a->size) { a->size *= 2; a->array = krealloc(a->array, a->size * sizeof(unsigned long), GFP_KERNEL); } a->array[a->used++] = element; } void cleanup_exit(void) /* Exit Module */ { printk(KERN_INFO "%s","REMOVING MODULEn"); } /* End of Exit Module */ module_init(iterate_init); /* Load Module MACRO */ module_exit(cleanup_exit); /* Remove Module MACRO */ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("ITERATE THROUGH ALL PROCESSES/CHILD PROCESSES IN THE OS"); MODULE_AUTHOR("G8C");
Makefile
obj-m += main.o test.o run: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules sudo insmod main.ko sleep 3s sudo rmmod main sudo dmesg -c all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Advertisement
Answer
I did more digging and found some functions that are helpful.
Include these:
#include <linux/resource.h> #include <linux/time.h> #include <linux/sched.h>
Then, if you wanna see some info with only the process ID:
struct task_struct *p; p = pid_task(find_vpid(pid), PIDTYPE_PID);//task structure of related p_id int y = p->prio;//priority of the process
Or if you just wanna set priorities(set_user_nice actually changes priorities in real time, not just the nice value):
set_user_nice(p, long_int_nice_value);