Skip to content

Haseeb702/Linux-Process-Monitor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TITLE: myMonitoringTool Assignment 3

  1. Metadata    Author: Haseeb Afzal    Date: 09/04/2025

  2. Introduction/Rationale The project is about creating a tool to display the cpu usage, memory usage, core count, and frequency of your pc

  3. Description of how you solve/approach the problem First I copied the all the functions from Assignment 1 and parsed them the same way as assignment1. then i went and fixed the errors that I had in my program, my problem was that first I had to split my functions into 3 module so i split into driver.c, info.c, info.h, printing.c, printing.h. First thing i did was fix the parsing for positional arguments to have a flag rather than its own case, then I went and fixed the cpu issue for my graph not updating. then I went and fixed the delay for my graph since I was doing tdelay *2 due to a mistake. Then i fix my cpu usage with the assignment speciifications. then i fixed cpu and core count since that was incorrect, then I stqarted on the new features I basicall forked the 4 functions that got the data concurrently, then I read the data from all 4 pipes after. Then what I did was write the data to the terminal like I usually do, Then i added an ignore for my ctrl+z singal and added a termination question for ctrl+c if user wants to continue or end the program

  4. Implementation    4.i - Describe first in sentences how did you implement your code. Just like I stated in my desccription, I got the functions from assignment1, then I parsed the strings and set flags to control which CLAs were being activated. Next, I split my code into three modules and have two header files. I split them based on info.c is data collection, printing.c is display functions, and driver.c is my main + signals. Then I wen and fixed issues in my code like the cpu frequency issues, my memory not updaating, my incorrect flag arguments which were messing up my parsing. then I fixed my graph timing because it was tdelay*2 since I delayed twice in my code by accident. Then i wen and implemneted the new things like the signal processing, i used the lecture stuff + man page to handle SIGSTP and also looked at stackoverflow to ignore the process suspension that was happening using termios. Then I worked on my ctrl+c signal handle with sigaction and a custom handler. Then i added a global flag for the signal and created a signal children handler that stops the children while the question is being asked and continues them when someone selects no using the kill() command. Then I added pipes into my previous if statements from assignment one and forked each data collection function using a non blocking pipe (stack overflow) because my pipe kept on reading an empty pipe which caused problems. I set up the pipes like the lectures and read them all at once later in the code

   4.ii - The modules you created and functions within them.

#define _POSIX_C_SOURCE 200809L //the manpage tells u to use this macro with this version(i found version on stackoverflow) #include <unistd.h> // fork(), pipe(), usleep(), read() #include <stdio.h> // standard i/o #include <stdlib.h> //standard library #include <string.h> //for strcmp and other string fxn #include <signal.h> // to catch signal using sigaciton(), signal() #include <termios.h> // this pauses input from going to the terminal #include <sys/wait.h> // this is word the waitpid() fxn #include <fcntl.h> // For fcntl(), reference #5 #include <sys/sysinfo.h> // for sysinfo() #include <unistd.h> //for usleep() #include "info.h" // CpuInfo, getCpuUsage(), and other calculation fxns #include "printing.h" // displayParameter(), getAllSamples(), and other display fxns    4.iii - Describe the functions in sentences, e.g. this function does this and that and uses this and that sources, system calls, libraries, etc.            DO NOT COPY the documentation from your code driver.c module

  • void handler_sigint(int sig): this takes a signal and sets the global flag to 1
  • void checkChildProcess(Pid_child *pid): takes a Pid_child struct as a pointer (pid) and uses it to check if SIGINT is detected and if so it pauses the program and continues it using kill() if the user chooses not to terminate, uses the unistd, string.h, stdio
  • int main(int argc, char **argv): this function takes the cla amount and cla array of strings and parses through them, this uses the info.h, and printing.h mdoules for a lot of functions. this part I added pipes into my previous if statements from assignment one and forked each data collection function using a non blocking pipe (stack overflow) because my pipe kept on reading an empty pipe which caused problems. I set up the pipes like the lectures and read them all at once later in the code, I used the fcntl() library as shown in ref #5 stack overflow to create a "non blocking pipe" which was needed to read properly from the info, i also use termios to use tcgetattr to disable the ctrl+z and file process suspension output which was causing issues for me. I also used signal.h for sigaction() and signal() to help with the signals, i used unistd for the usleep and fork(), pipe(), read(), close(). and sys/wait.h was for waitpid to stop zombie processes. info.c module:
  • float getTotalMemory(): used sysinfo to get the toal memory from the system
  • float getUsedMemory(): used sysinfo again to get the total and free memory and then subtract it and return float value of used memory
  • CpuStats parseCpuStats(): used open(/proc/stat) to check the cpu stats and then parsed the whole line into the struct for cpustats and then returned that struct with all the long data in there
  • int parseCpuCore(): open /proc/cpuinfo, check for errors and then use the fgets to read through every line of the file and whenever processor: is seen increment core count by 1
  • float parseCpuFreq(): open /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq file for read, and then parse the float value and return it in GHz
  • long addTotalTime(CpuStats stats): takes in a CpuStats struct and adds up all the struct long variable for cpu stats and returns them
  • float getCpuUsage(int tdelay): this was in the assingment description, take a tdelay int parameter and take two cpuStat calls withing a usleep(tdelay) time between them and then do the calculations as said in the description and return the cpuUsage. this uses unistd.h function printing.c
  • void displayParameter(int samples, int tdelay): this takes in samples and tdelay and prints them out with tdelay converted to seconds.
  • void printMemory(float usedMemory[], int samples, int j) takes in a float array, int samples and int j. This prints the graph depending on the values in the array. prints a graphical representation of the memory usage over samples
  • void getMemoryPerSample(int samples, int tdelay): takes in two paramters, samples and tdelay repeatedly calls printMemory dpending on sample size with an added delay using usleep (which is not an std=c99) but still works since i need a microsecond input which sleep doesnt provide clear the screen using escape code with starts from the bottom and deletes up 12 lines
  • void printCpuUsage(float usedCpu[], int samples, int j) takes in a float array, int samples and int j. This prints the graph depending on the values in the array. prints a graphical representation of the cpu usage over samples
  • void getCpuUsagePerSample(int samples, int tdelay): takes in two paramters, samples and tdelay repeatedly calls printCpuUsage dpending on sample size with an added delay using usleep (which is not an std=c99)but still works since i need a microsecond input which sleep doesnt provide, clear the screen using escape code with starts from the bottom and deletes up 13 lines resets the cpu total usage at the header
  • void getAllSamples(int samples, int tdelay): takes in two paramters, samples and tdelay repeatedly calls printCpuUsage and printMemory with refreshdepending on sample size with an added delay using usleep (which is not an std=c99) but still works since i need a microsecond input which sleep doesnt provide clear the screen using escape code with starts from a saved point in the graph and then inputs the next value and then restores it again with restore cursor escape code
  • void printCores(): gives a physical representation of the cpu cores and gives the frequency and core count
  1. Include a pseudo-code of your code OR flow chart or diagram of your program and corresponding functions' calls flowchart     Refs.     https://www.geeksforgeeks.org/what-is-pseudocode-a-complete-tutorial/     https://en.wikipedia.org/wiki/Flowchart      https://draw.io

  2. Instructions on how to compile your code I have a makefile to compile my code, so what you do is: make run ^do this if you want to run the file make clear ^do this to clear all the leftover files make run ARGS="" ^ use this and then input any cla necessary inside the quotation marks like how I did in my test cases My makefile has comments explaining it but also, Describe how to compile the code, dependencies with libraries:

  • In terms of dependencies with libraries, everything is already in the a3 folder and can be used at any time. The code can be compiled with the make as stated above For makefiles add details about the rules and what they do and how to use them: ^for my makefile I have the CC and CFLAGS like usual. then I have the myMonitoringTool rule which has the *.o dependency. This compiles the code with all the flags and turns it into an executable. Next is the %.o rule which has %.c dependencies which compiles the .c file into an object file. Then I have the run rule, which runs the executable with the CLA's that are provided with ARGS Then I have the phony target which ensures that clean is executed when it is called. Then I have the clean rule which executes and removes all .o files and the myMonitoringTool executable and it has -f which makes sure it always removes the files
  1. Expected Results

make run

Nbr of Samples: 20 -- every 500000 microsecs (0.500 secs)

v Memory 8.72 GB 15.31 GB |
|
|
|
|
|#################### |
|
|
|
|
0.00 GB _____________________

v CPU 7.04 % 100 % |
|
|
|
|
|
|
|
|
|
|:::::::::::::::::::: 0 % _____________________ ^Z v Number of Cores: 20 @ 4.80 GHz +--+ +--+ +--+ +--+ | | | | | | | | +--+ +--+ +--+ +--+ +--+ +--+ +--+ +--+ | | | | | | | | +--+ +--+ +--+ +--+ +--+ +--+ +--+ +--+ | | | | | | | | +--+ +--+ +--+ +--+ +--+ +--+ +--+ +--+ | | | | | | | | +--+ +--+ +--+ +--+ +--+ +--+ +--+ +--+ | | | | | | | | +--+ +--+ +--+ +--+

make run ARGS="--memory"

Nbr of Samples: 20 -- every 500000 microsecs (0.500 secs)

v Memory 8.71 GB 15.31 GB |
|
|
|
|
|#################### |
|
|
|
|
0.00 GB _____________________

make run ARGS="--cpu"

Nbr of Samples: 20 -- every 500000 microsecs (0.500 secs)

v CPU 5.00 % 100 % |
|
|
|
|
|
|
|
|
|
|:::::::::::::::::::: 0 % _____________________

make run ARGS="--cores"

Nbr of Samples: 20 -- every 500000 microsecs (0.500 secs)

v Number of Cores: 20 @ 4.80 GHz +--+ +--+ +--+ +--+ | | | | | | | | +--+ +--+ +--+ +--+ +--+ +--+ +--+ +--+ | | | | | | | | +--+ +--+ +--+ +--+ +--+ +--+ +--+ +--+ | | | | | | | | +--+ +--+ +--+ +--+ +--+ +--+ +--+ +--+ | | | | | | | | +--+ +--+ +--+ +--+ +--+ +--+ +--+ +--+ | | | | | | | | +--+ +--+ +--+ +--+

make run ARGS="10 200000"

Nbr of Samples: 10 -- every 200000 microsecs (0.200 secs)

v Memory 8.71 GB 15.31 GB |
|
|
|
|
|########## |
|
|
|
|
0.00 GB ___________

v CPU 5.24 % 100 % |
|
|
|
|
|
|
|
|
|
|:::::::::: 0 % ___________

v Number of Cores: 20 @ 4.80 GHz +--+ +--+ +--+ +--+ | | | | | | | | +--+ +--+ +--+ +--+ +--+ +--+ +--+ +--+ | | | | | | | | +--+ +--+ +--+ +--+ +--+ +--+ +--+ +--+ | | | | | | | | +--+ +--+ +--+ +--+ +--+ +--+ +--+ +--+ | | | | | | | | +--+ +--+ +--+ +--+ +--+ +--+ +--+ +--+ | | | | | | | | +--+ +--+ +--+ +--+

make run ARGS="--tdelay=200000 --samples=10"

Nbr of Samples: 10 -- every 200000 microsecs (0.200 secs)

v Memory 8.72 GB 15.31 GB |
|
|
|
|
|########## |
|
|
|
|
0.00 GB ___________

v CPU 5.49 % 100 % |
|
|
|
|
|
|
|
|
|
|:::::::::: 0 % ___________

v Number of Cores: 20 @ 4.80 GHz +--+ +--+ +--+ +--+ | | | | | | | | +--+ +--+ +--+ +--+ +--+ +--+ +--+ +--+ | | | | | | | | +--+ +--+ +--+ +--+ +--+ +--+ +--+ +--+ | | | | | | | | +--+ +--+ +--+ +--+ +--+ +--+ +--+ +--+ | | | | | | | | +--+ +--+ +--+ +--+ +--+ +--+ +--+ +--+ | | | | | | | | +--+ +--+ +--+ +--+

  1. Test Cases

make run

this prints out everything you can do ctrl+z and it will be ignored and you can do ctrl+c and it will ask if I want to terminate, y will terminate and n will continue as usual

make run ARGS="--memory"

prints out the memory graph

make run ARGS="--cpu"

prints out cpu graph

make run ARGS="--cores"

prints out cores

make run ARGS="10 200000"

10 samples and 0.2s delay prints everything

make run ARGS="--tdelay=200000 --samples=10"

same as above

  1. Disclaimers
  • everything should work fine but if an invalid CLA is input then the program will fail and segmentation fault will happen
  • If you try to input a positional argument to a pid that doesnt exist then it will fail and segmentation fault will happen
  • make sure makefile is used
  • dont spam the ctrl+z or ctrl+c and dont use them simaltaneously or else it will cause terminal problems
  1. References #1 https://man7.org/linux/man-pages/man2/sigaction.2.html #2 https://man7.org/linux/man-pages/man2/signal.2.html #3 https://stackoverflow.com/questions/68602211/forcing-a-terminal-not-to-print-ctrl-hotkeys-when-signals-are-caught #4 https://tldp.org/LDP/lpg/node11.html #5 https://man7.org/linux/man-pages/man2/wait.2.html #6 https://stackoverflow.com/questions/7794273/c-using-signals-to-stop-child-processes #7 https://pubs.opengroup.org/onlinepubs/7908799/xsh/dirent.h.html #8 https://www.kernel.org/doc/Documentation/cpu-freq/user-guide.txt #9 https://stackoverflow.com/questions/59922972/how-to-stop-echo-in-terminal-using-c #10 https://man7.org/linux/man-pages/man1/kill.1.html #11 https://stackoverflow.com/questions/76444252/linux-tcgetattr-followed-by-tcsetattr-not-working #12 https://stackoverflow.com/questions/54619208/what-happens-when-i-try-to-read-from-a-pipe-without-writing-to-it

Your code must have:     - comments in the code, these are in/between lines     - documentation placed immediately after the function declaration line,       describing what each of the functions does and which parametersit takes and output it produces     - documentation style must be done using the following format:         ///|> descry: description of the function         ///|> arg_i: description and type of argument i         ///|> arg_ii: description and type of argument ii         ///|> ...         ///|> returning: return type and description -- even if it does not return anything!    E.g.     void plotGenerator(int iteration, float CPU_measurement) {         ///|> descry: this function generates an xy-plot using values for x and y coordinates         ///|> iteration: x value for the plot, type integer         ///|> CPU_measurement: y value for the plot, type float         ///_|> returning: this function does not return anything

    float CPU_measure(int iteration, float tdelay) {         ///|> descry: this function measures the CPU utlization in a given moment of time         ///|> iteration: indicates the current iteration number, type integer         ///|> tdelat: indicates the delay between samples, type float         ///|> returning: this function returns the relative measurement of CPU utilization as a percentage, type: float

About

The Process Monitor is about creating a tool to display the cpu usage, memory usage, core count, and frequency of your Linux device

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors