reworked linking logic to be a little clearer, added 'kernel' node

This commit is contained in:
Dan Snyder 2025-01-14 19:24:12 -05:00
parent 4e9da25009
commit 3960919efe
2 changed files with 54 additions and 39 deletions

View File

@ -6,7 +6,6 @@
typedef struct st_process {
// For our own purposes
struct st_process *next; // next process in order we read them
struct st_process *prev; // previous process read
struct st_process *parent; // parent process
struct st_process *child; // pointer to first child
struct st_process *sibling; // pointer to next sibling

View File

@ -95,33 +95,6 @@ int parseIOFile(Process *proc, char *filedata) {
return 0;
}
void linkFamily(Process *head) {
int orphans = 1;
while (orphans) {
orphans = 0;
Process *current = head;
// while on an actual process node, and it has a parent link or doesn't need a parent link
while (current != NULL && (current->parent != NULL || current->ppid <= 0)) current = current->next;
if (current == NULL) break;
orphans = 1;
Process *parent = head;
while (parent != NULL && parent->pid != current->ppid) parent = parent->next;
if (parent == NULL) {
printf("Found orphan process: %d\n", current->pid);
current->ppid = -1;
continue;
}
// We have a parent and a child ready to be united
current->parent = parent;
Process **placement = &(parent->child);
while ((*placement) != NULL) placement = &((*placement)->sibling);
*placement = current;
}
}
int resetVisits(Process *head) {
Process *current = head;
int processCount = 0;
@ -135,6 +108,37 @@ int resetVisits(Process *head) {
return processCount;
}
void linkFamily(Process *head) {
int orphans = resetVisits(head);
while (orphans) {
Process *cur, *parent = head;
// get next unvisited node
while (parent != NULL && parent->visited) parent = parent->next;
if (parent == NULL) { // sanity check
printf("Error: Found %d orphan process(es):\n", orphans);
break;
}
parent->visited = 1;
// Search for children
for (cur = head; cur != NULL; cur = cur->next) {
if (cur->ppid != parent->pid) continue;
// We have a parent and child ready to be united
orphans--;
cur->parent = parent;
// place child amongst siblings, if any are present
Process **placement = &(parent->child);
while ((*placement) != NULL) placement = &((*placement)->sibling);
*placement = cur;
}
}
}
void printFamilyTree(Process *head) {
int processCount = resetVisits(head);
int visited = 0;
@ -253,13 +257,27 @@ char *readProcesses(char *procdir) {
char first;
FILE *file;
Process *cur = calloc(1, sizeof(Process));
Process *head = cur;
Process *head = calloc(1, sizeof(Process));
Process *cur = head;
Process *prev = NULL;
lxcinfo *lxcs = NULL;
// First process node is the kernel
strcpy(cur->label, "kernel");
cur->lxc = -1;
cur->visited = 1;
while ((pDirent = readdir(pDir)) != NULL) {
first = pDirent->d_name[0];
if (first < '0' || first > '9') continue;
if (cur->visited) {
// get new process node if necessary
prev = cur;
cur->next = calloc(1, sizeof(Process));
cur = cur->next;
}
sprintf(fname, "/proc/%s/status", pDirent->d_name);
file = fopen(fname, "rb");
if (file == NULL) continue;
@ -299,21 +317,19 @@ char *readProcesses(char *procdir) {
sscanf(cur->cpuset, "/lxc/%d/ns", &cur->lxc);
if (getLXCInfo(&lxcs, cur->lxc) == NULL)
printf("Failed to read LXC config <%d>\n", cur->lxc);
} else {
cur->lxc = -1;
}
nextProcess:
cur->next = calloc(1, sizeof(Process));
cur->next->prev = cur;
cur = cur->next;
cur->visited = 1;
}
// clean up unused last node
cur = cur->prev;
free(cur->next);
cur->next = NULL;
if (!cur->visited) {
// if there's an unused node, remove it
prev->next = NULL;
free(cur);
}
linkFamily(head);
aggregateStats(head);