Testing actual parsing of /proc/<pid>/stat

This commit is contained in:
Dan Snyder 2025-01-13 01:17:12 -05:00
parent 1c91288dbc
commit 53f8871381
2 changed files with 155 additions and 2 deletions

25
src/process.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef PROCESS_MON_H
#define PROCESS_MON_H
#include <stdint.h>
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

View File

@ -1,10 +1,116 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <time.h> #include <time.h>
#include <unistd.h>
#include <stdint.h>
#include <dirent.h> #include <dirent.h>
#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##inclusive<exclusive-inclusive; i##inclusive++) \
location = strchr(location, ' ') + 1;
int parseStatFile(Process *proc, char *filedata) {
char *location = filedata;
// (1) pid - %d
proc->pid = 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[]) { int main(int argc, char *argv[]) {
struct dirent *pDirent; struct dirent *pDirent;
@ -31,14 +137,24 @@ int main(int argc, char *argv[]) {
char *fname = malloc(1024); char *fname = malloc(1024);
FILE *file; FILE *file;
Process *cur = malloc(sizeof(Process));
cur->label = malloc(256);
Process *head = cur;
while ((pDirent = readdir(pDir)) != NULL) { while ((pDirent = readdir(pDir)) != NULL) {
char first = pDirent->d_name[0]; char first = pDirent->d_name[0];
if (first < '0' || first > '9') continue; if (first < '0' || first > '9') continue;
sprintf(fname, "/proc/%s/stat", pDirent->d_name); sprintf(fname, "/proc/%s/stat", pDirent->d_name);
file = fopen(fname, "rb"); file = fopen(fname, "rb");
fread(filedata, 1, 4096, file); fread(filedata, 1, 4096, file);
fclose(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"); strcat(fname, "us");
file = fopen(fname, "rb"); file = fopen(fname, "rb");
fread(filedata, 1, 4096, file); fread(filedata, 1, 4096, file);
@ -47,6 +163,18 @@ int main(int argc, char *argv[]) {
printf("[%s]\n", filedata); 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. // Close directory and exit.
closedir(pDir); closedir(pDir);