initial commit
This commit is contained in:
26
Makefile
Normal file
26
Makefile
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# Variables
|
||||||
|
CC = gcc
|
||||||
|
CFLAGS = -Wall -Wextra -Werror
|
||||||
|
TARGET = code_analyzer
|
||||||
|
SCRIPT = analyze.sh
|
||||||
|
INSTALL_DIR = /usr/local/bin
|
||||||
|
|
||||||
|
# Default target
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
# Compile the C program
|
||||||
|
$(TARGET): code_analyzer.c
|
||||||
|
$(CC) $(CFLAGS) -o $(TARGET) code_analyzer.c
|
||||||
|
|
||||||
|
# Install the script and binary
|
||||||
|
install: $(TARGET) $(SCRIPT)
|
||||||
|
sudo cp $(TARGET) $(INSTALL_DIR)/$(TARGET)
|
||||||
|
sudo cp $(SCRIPT) $(INSTALL_DIR)/$(SCRIPT)
|
||||||
|
sudo chmod +x $(INSTALL_DIR)/$(SCRIPT)
|
||||||
|
|
||||||
|
# Clean up the binary
|
||||||
|
clean:
|
||||||
|
rm -f $(TARGET)
|
||||||
|
|
||||||
|
# Phony targets
|
||||||
|
.PHONY: all install clean
|
||||||
8
analyze.sh
Executable file
8
analyze.sh
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [ $# -lt 2 ]; then
|
||||||
|
echo "Usage: $0 <command> [args] <duration>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
/usr/local/bin/code_analyzer "$@"
|
||||||
200
code_analyzer.c
Normal file
200
code_analyzer.c
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/statvfs.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <linux/hdreg.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
// Function to get the CPU usage of a process
|
||||||
|
double get_cpu_usage(int pid) {
|
||||||
|
char path[40];
|
||||||
|
FILE *file;
|
||||||
|
sprintf(path, "/proc/%d/stat", pid);
|
||||||
|
file = fopen(path, "r");
|
||||||
|
if (!file) return -1;
|
||||||
|
|
||||||
|
long unsigned int utime, stime, cutime, cstime;
|
||||||
|
double total_time;
|
||||||
|
long unsigned int starttime;
|
||||||
|
unsigned long int total_jiffies;
|
||||||
|
|
||||||
|
fscanf(file, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %*u %*u %lu %lu %lu %lu %*d %*d %*d %*d %lu",
|
||||||
|
&utime, &stime, &cutime, &cstime, &starttime);
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
total_time = (double) (utime + stime + cutime + cstime);
|
||||||
|
total_jiffies = sysconf(_SC_CLK_TCK);
|
||||||
|
return total_time / total_jiffies;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to get the memory usage of a process
|
||||||
|
long get_memory_usage(int pid) {
|
||||||
|
char path[40], line[100];
|
||||||
|
FILE *file;
|
||||||
|
sprintf(path, "/proc/%d/status", pid);
|
||||||
|
file = fopen(path, "r");
|
||||||
|
if (!file) return -1;
|
||||||
|
|
||||||
|
long memory = -1;
|
||||||
|
while (fgets(line, 100, file)) {
|
||||||
|
if (strncmp(line, "VmRSS:", 6) == 0) {
|
||||||
|
sscanf(line + 6, "%ld", &memory);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
return memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to get disk usage
|
||||||
|
void get_disk_usage(const char *path, long *total, long *free) {
|
||||||
|
struct statvfs stat;
|
||||||
|
if (statvfs(path, &stat) != 0) {
|
||||||
|
*total = -1;
|
||||||
|
*free = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*total = stat.f_blocks * stat.f_frsize;
|
||||||
|
*free = stat.f_bfree * stat.f_frsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to get disk I/O usage
|
||||||
|
void get_disk_io_usage(int pid, long *read_bytes, long *write_bytes) {
|
||||||
|
char path[40], line[100];
|
||||||
|
FILE *file;
|
||||||
|
sprintf(path, "/proc/%d/io", pid);
|
||||||
|
file = fopen(path, "r");
|
||||||
|
if (!file) {
|
||||||
|
*read_bytes = -1;
|
||||||
|
*write_bytes = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (fgets(line, 100, file)) {
|
||||||
|
if (strncmp(line, "read_bytes:", 11) == 0) {
|
||||||
|
sscanf(line + 11, "%ld", read_bytes);
|
||||||
|
} else if (strncmp(line, "write_bytes:", 12) == 0) {
|
||||||
|
sscanf(line + 12, "%ld", write_bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to get network usage
|
||||||
|
void get_network_usage(long *rx_bytes, long *tx_bytes) {
|
||||||
|
FILE *file;
|
||||||
|
char line[256];
|
||||||
|
*rx_bytes = 0;
|
||||||
|
*tx_bytes = 0;
|
||||||
|
|
||||||
|
file = fopen("/proc/net/dev", "r");
|
||||||
|
if (!file) return;
|
||||||
|
|
||||||
|
// Skip the first two lines
|
||||||
|
fgets(line, sizeof(line), file);
|
||||||
|
fgets(line, sizeof(line), file);
|
||||||
|
|
||||||
|
while (fgets(line, sizeof(line), file)) {
|
||||||
|
char iface[32];
|
||||||
|
long rx, tx;
|
||||||
|
sscanf(line, "%s %ld %*d %*d %*d %*d %*d %*d %*d %ld", iface, &rx, &tx);
|
||||||
|
*rx_bytes += rx;
|
||||||
|
*tx_bytes += tx;
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to run a command and analyze its usage for a given duration
|
||||||
|
void analyze_command(char *command[], int duration) {
|
||||||
|
pid_t pid = fork();
|
||||||
|
if (pid == 0) {
|
||||||
|
// Child process: Execute the command
|
||||||
|
execvp(command[0], command);
|
||||||
|
perror("execvp");
|
||||||
|
exit(1);
|
||||||
|
} else if (pid > 0) {
|
||||||
|
// Parent process: Monitor the child process
|
||||||
|
double start_cpu_time = get_cpu_usage(pid);
|
||||||
|
long start_rx_bytes, start_tx_bytes;
|
||||||
|
get_network_usage(&start_rx_bytes, &start_tx_bytes);
|
||||||
|
|
||||||
|
long total_memory_usage = 0;
|
||||||
|
long total_read_bytes = 0, total_write_bytes = 0;
|
||||||
|
int sample_count = 0;
|
||||||
|
|
||||||
|
time_t start = time(NULL);
|
||||||
|
while (time(NULL) - start < duration) {
|
||||||
|
long memory_usage = get_memory_usage(pid);
|
||||||
|
long read_bytes, write_bytes;
|
||||||
|
get_disk_io_usage(pid, &read_bytes, &write_bytes);
|
||||||
|
|
||||||
|
if (memory_usage < 0 || read_bytes < 0 || write_bytes < 0) {
|
||||||
|
fprintf(stderr, "Error: Could not retrieve information for PID %d\n", pid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
total_memory_usage += memory_usage;
|
||||||
|
total_read_bytes = read_bytes; // Update to reflect actual read bytes
|
||||||
|
total_write_bytes = write_bytes; // Update to reflect actual write bytes
|
||||||
|
sample_count++;
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
double end_cpu_time = get_cpu_usage(pid);
|
||||||
|
long end_rx_bytes, end_tx_bytes;
|
||||||
|
get_network_usage(&end_rx_bytes, &end_tx_bytes);
|
||||||
|
|
||||||
|
kill(pid, SIGKILL); // Terminate the process after the duration
|
||||||
|
waitpid(pid, NULL, 0); // Wait for the child process to finish
|
||||||
|
|
||||||
|
double cpu_time_diff = end_cpu_time - start_cpu_time;
|
||||||
|
long avg_memory_usage = total_memory_usage / sample_count;
|
||||||
|
long total_rx_bytes = end_rx_bytes - start_rx_bytes;
|
||||||
|
long total_tx_bytes = end_tx_bytes - start_tx_bytes;
|
||||||
|
|
||||||
|
int num_cores = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
|
double elapsed_time = duration;
|
||||||
|
double cpu_usage_percentage = (cpu_time_diff / elapsed_time) * 100.0 * num_cores;
|
||||||
|
|
||||||
|
long disk_total, disk_free;
|
||||||
|
get_disk_usage("/", &disk_total, &disk_free);
|
||||||
|
|
||||||
|
printf("Command: %s\n", command[0]);
|
||||||
|
printf("CPU Usage: %.2f%%\n", cpu_usage_percentage);
|
||||||
|
printf("Average Memory Usage: %ld kB\n", avg_memory_usage);
|
||||||
|
printf("Disk Read Bytes: %ld\n", total_read_bytes);
|
||||||
|
printf("Disk Write Bytes: %ld\n", total_write_bytes);
|
||||||
|
printf("Network Received Bytes: %ld\n", total_rx_bytes);
|
||||||
|
printf("Network Transmitted Bytes: %ld\n", total_tx_bytes);
|
||||||
|
printf("Disk Total: %ld bytes\n", disk_total);
|
||||||
|
printf("Disk Free: %ld bytes\n", disk_free);
|
||||||
|
} else {
|
||||||
|
perror("fork");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
if (argc < 3) {
|
||||||
|
fprintf(stderr, "Usage: %s <command> [args] <duration>\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int duration = atoi(argv[argc - 1]); // The last argument is the duration
|
||||||
|
argv[argc - 1] = NULL; // Remove the duration from the command arguments
|
||||||
|
|
||||||
|
analyze_command(argv + 1, duration);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user