#include #include #include #include #include #include #include #include #define DEFAULT_NUM_LEN 512 char *itoa(long num, char *strnum, size_t size){ int isNegative = 0; if(num == 0){ strnum[0] = '0'; strnum[1] = '\0'; return strnum; } if(num < 0){ isNegative = 1; num = -num; } int counter = 0; while(num > 0 && counter <(int)(size-1)){ strnum[counter] = num % 10 + '0'; num /= 10; counter ++; } if(isNegative){ strnum[counter] = '-'; counter++; } strnum[counter] = '\0'; for(int i=0; id_type == DT_DIR && is_numeric_dir(ent->d_name)) { count++; } } closedir(dir); return count; } static long count_threads_total(void) { DIR *dir = opendir("/proc"); if (!dir) { return 0; } long total = 0; struct dirent *ent; while ((ent = readdir(dir)) != NULL) { if (ent->d_type != DT_DIR || !is_numeric_dir(ent->d_name)) { continue; } char path[256]; snprintf(path, sizeof(path), "/proc/%s/status", ent->d_name); FILE *f = fopen(path, "r"); if (!f) { continue; } char line[256]; while (fgets(line, sizeof(line), f)) { if (strncmp(line, "Threads:", 8) == 0) { long v = 0; if (sscanf(line, "Threads: %ld", &v) == 1) { total += v; } break; } } fclose(f); } closedir(dir); return total; } static void read_loadavg(double *l1, double *l5, double *l15) { FILE *f = fopen("/proc/loadavg", "r"); if (!f) { *l1 = *l5 = *l15 = 0.0; return; } if (fscanf(f, "%lf %lf %lf", l1, l5, l15) != 3) { *l1 = *l5 = *l15 = 0.0; } fclose(f); } static void read_meminfo(long *total_kb, long *avail_kb) { FILE *f = fopen("/proc/meminfo", "r"); if (!f) { *total_kb = 0; *avail_kb = 0; return; } char key[64]; long value = 0; char unit[16]; while (fscanf(f, "%63s %ld %15s", key, &value, unit) == 3) { if (strcmp(key, "MemTotal:") == 0) { *total_kb = value; } else if (strcmp(key, "MemAvailable:") == 0) { *avail_kb = value; } if (*total_kb && *avail_kb) { break; } } fclose(f); } static void read_self_status(long *rss_kb, long *vsz_kb, long *stk_kb, long *heap_kb, long *threads) { FILE *f = fopen("/proc/self/status", "r"); if (!f) { *rss_kb = *vsz_kb = *stk_kb = *heap_kb = *threads = 0; return; } char line[256]; while (fgets(line, sizeof(line), f)) { if (sscanf(line, "VmRSS: %ld", rss_kb) == 1) { continue; } if (sscanf(line, "VmSize: %ld", vsz_kb) == 1) { continue; } if (sscanf(line, "VmStk: %ld", stk_kb) == 1) { continue; } if (sscanf(line, "VmData: %ld", heap_kb) == 1) { continue; } if (sscanf(line, "Threads: %ld", threads) == 1) { continue; } } fclose(f); } static long read_self_ticks(void) { FILE *f = fopen("/proc/self/stat", "r"); if (!f) { return 0; } long utime = 0; long stime = 0; char buf[512]; if (fgets(buf, sizeof(buf), f)) { char *p = strrchr(buf, ')'); if (p) { long vals[64]; int n = 0; p++; while (*p && n < 64) { while (*p == ' ') { p++; } if (!*p) { break; } vals[n++] = strtol(p, &p, 10); } if (n > 13) { utime = vals[11]; stime = vals[12]; } } } fclose(f); return utime + stime; } static void read_cpu_total(long *total, long *idle) { FILE *f = fopen("/proc/stat", "r"); if (!f) { *total = 0; *idle = 0; return; } char cpu[8]; long user = 0, nice = 0, system = 0, idle_v = 0, iowait = 0, irq = 0, softirq = 0, steal = 0; if (fscanf(f, "%7s %ld %ld %ld %ld %ld %ld %ld %ld", cpu, &user, &nice, &system, &idle_v, &iowait, &irq, &softirq, &steal) == 9) { *total = user + nice + system + idle_v + iowait + irq + softirq + steal; *idle = idle_v + iowait; } else { *total = 0; *idle = 0; } fclose(f); } static void format_timestamp(char *out, size_t size) { time_t now = time(NULL); struct tm tm_now; localtime_r(&now, &tm_now); strftime(out, size, "%Y-%m-%dT%H:%M:%S%z", &tm_now); } static double read_uptime(void) { FILE *f = fopen("/proc/uptime", "r"); if (!f) { return 0.0; } double up = 0.0; if (fscanf(f, "%lf", &up) != 1) { up = 0.0; } fclose(f); return up; } int main(void) { const char *csv_path = getenv("FORK_BOMB_CSV"); if (!csv_path || !*csv_path) { csv_path = "fork_bomb.csv"; } long proc_step = 50; const char *step_env = getenv("PROC_SAMPLE_STEP"); if (step_env && *step_env) { long v = strtol(step_env, NULL, 10); if (v > 0) { proc_step = v; } } FILE *csv = fopen(csv_path, "w"); if (!csv) { perror("fopen csv"); return 1; } fprintf(csv, "timestamp,elapsed_s,load1,load5,load15,mem_total_kb,mem_available_kb,mem_used_kb,proc_count,thread_count_total,pid,cpu_pct,sys_cpu_pct,rss_kb,vsz_kb,stack_kb,heap_kb,proc_threads\n"); long count = 0; long prev_proc_count = 0; long proc_accum = 0; double start_uptime = read_uptime(); long prev_cpu_total = 0; long prev_cpu_idle = 0; read_cpu_total(&prev_cpu_total, &prev_cpu_idle); long prev_ticks = read_self_ticks(); double prev_uptime = read_uptime(); long clk_tck = sysconf(_SC_CLK_TCK); if (clk_tck <= 0) { clk_tck = 100; } while (1) { pid_t pid = fork(); if (pid < 0) { perror("fork"); break; } if (pid == 0) { pause(); return 0; } count++; long proc_count = count_processes(); if (prev_proc_count > 0) { long delta = proc_count - prev_proc_count; if (delta > 0) { proc_accum += delta; } } prev_proc_count = proc_count; if (proc_accum >= proc_step) { proc_accum = 0; double now_uptime = read_uptime(); double elapsed_s = now_uptime - start_uptime; double load1 = 0.0, load5 = 0.0, load15 = 0.0; read_loadavg(&load1, &load5, &load15); long mem_total = 0, mem_avail = 0; read_meminfo(&mem_total, &mem_avail); long mem_used = mem_total - mem_avail; long thread_total = count_threads_total(); long rss = 0, vsz = 0, stk = 0, heap = 0, proc_threads = 0; read_self_status(&rss, &vsz, &stk, &heap, &proc_threads); long cur_ticks = read_self_ticks(); double dt = now_uptime - prev_uptime; double cpu_pct = 0.0; if (dt > 0.0) { cpu_pct = (100.0 * (double)(cur_ticks - prev_ticks)) / (dt * (double)clk_tck); } prev_uptime = now_uptime; prev_ticks = cur_ticks; long cpu_total = 0; long cpu_idle = 0; read_cpu_total(&cpu_total, &cpu_idle); long dt_total = cpu_total - prev_cpu_total; long dt_idle = cpu_idle - prev_cpu_idle; double sys_cpu_pct = 0.0; if (dt_total > 0) { sys_cpu_pct = 100.0 * (double)(dt_total - dt_idle) / (double)dt_total; } prev_cpu_total = cpu_total; prev_cpu_idle = cpu_idle; char ts[64]; format_timestamp(ts, sizeof(ts)); fprintf(csv, "%s,%.3f,%.2f,%.2f,%.2f,%ld,%ld,%ld,%ld,%ld,%ld,%.2f,%.2f,%ld,%ld,%ld,%ld,%ld\n", ts, elapsed_s, load1, load5, load15, mem_total, mem_avail, mem_used, proc_count, thread_total, (long)getpid(), cpu_pct, sys_cpu_pct, rss, vsz, stk, heap, proc_threads); fflush(csv); } } fclose(csv); return 0; }