diff --git a/src/process.h b/src/process.h new file mode 100644 index 0000000..724a096 --- /dev/null +++ b/src/process.h @@ -0,0 +1,25 @@ +#ifndef PROCESS_MON_H +#define PROCESS_MON_H + +#include + +typedef struct st_process { + // For our own purposes + struct st_process *next; + struct st_process *prev; + // attributes identifying thread + int lxc; + int pid; + int ppid; + int tgid; + int level; + char *label; + int iskernel; + // statistics - each outputs 1 line per process + uint64_t cpuTime; + uint64_t childCpuTime; + uint64_t nThreads; + uint64_t resident; +} Process; + +#endif \ No newline at end of file diff --git a/src/server.c b/src/server.c index ad8df42..d84b11d 100644 --- a/src/server.c +++ b/src/server.c @@ -1,10 +1,116 @@ #include #include +#include #include #include #include #include +#include +#include #include +#include "process.h" + +static inline uint64_t fast_str2ull(char** str) { + uint64_t result = 0; + int maxlen = 20; // length of maximum value of 18446744073709551615 + + while (maxlen-- && **str >= '0' && **str <= '9') { + result *= 10; + result += **str - '0'; + (*str)++; + } + + return result; +} + +static int64_t fast_str2ll(char** str) { + bool neg = false; + + if (**str == '-') { + neg = true; + (*str)++; + } + + uint64_t res = fast_str2ull(str); + int64_t result = (int64_t) res; + + return neg ? -result : result; +} + +#define skipRange(inclusive,exclusive) \ + for (int i##inclusive=0; i##inclusivepid = fast_str2ull(&location); + location += 2; + + // (2) comm - %s + char *end = strrchr(location, ')'); + size_t length = end - location; + memcpy(proc->label, location, length); + proc->label[length] = 0; + location = end + 2; + + // (3) State - %c + location += 2; + + // (4) ppid - %d + proc->ppid = fast_str2ull(&location); + location += 1; + + // (5) pgrp - %d + proc->tgid = fast_str2ll(&location); + location += 1; + + if (proc->tgid != proc->pid) return -1; + + // (6) session - %d + location = strchr(location, ' ') + 1; + + // skip [7 - 14) + skipRange(7, 9); + + // (9) flags - %u + proc->iskernel = fast_str2ull(&location) & PS_KTHREAD; + location += 1; + + skipRange(10, 14); + + // (14) utime - %lu + proc->cpuTime = fast_str2ull(&location); + location += 1; + + // (15) stime - %lu + proc->cpuTime += fast_str2ull(&location); + location += 1; + + // (16) cutime - %lu + proc->childCpuTime = fast_str2ull(&location); + location += 1; + + // (17) cstime - %lu + proc->childCpuTime += fast_str2ull(&location); + location += 1; + + // skip 18-19 + skipRange(18, 20); + + // (20) - num_threads %ld + proc->nThreads = fast_str2ull(&location); + location += 1; + + // Skip 21-23 + skipRange(21,24); + + // (24) - rss %ld + proc->resident = fast_str2ull(&location); + location += 1; + + return 0; +} int main(int argc, char *argv[]) { struct dirent *pDirent; @@ -31,14 +137,24 @@ int main(int argc, char *argv[]) { char *fname = malloc(1024); FILE *file; + Process *cur = malloc(sizeof(Process)); + cur->label = malloc(256); + Process *head = cur; + while ((pDirent = readdir(pDir)) != NULL) { - char first = pDirent->d_name[0]; - if (first < '0' || first > '9') continue; + char first = pDirent->d_name[0]; + if (first < '0' || first > '9') continue; sprintf(fname, "/proc/%s/stat", pDirent->d_name); file = fopen(fname, "rb"); fread(filedata, 1, 4096, file); fclose(file); + if (parseStatFile(cur, filedata)) continue; + cur->next = malloc(sizeof(Process)); + cur->next->label = malloc(256); + cur->next->prev = cur; + cur = cur->next; + strcat(fname, "us"); file = fopen(fname, "rb"); fread(filedata, 1, 4096, file); @@ -47,6 +163,18 @@ int main(int argc, char *argv[]) { printf("[%s]\n", filedata); } + cur = cur->prev; + free(cur->next); + cur->next = NULL; + + int clocks = sysconf(_SC_CLK_TCK); + + cur = head; + while (cur != NULL) { + printf("proc_cpu_time{pid=\"%d\",ppid=\"%d\",label=\"%s\"} %d\n", cur->pid, cur->ppid, cur->label, cur->cpuTime); + cur = cur->next; + } + // Close directory and exit. closedir(pDir);