Testing actual parsing of /proc/<pid>/stat
This commit is contained in:
parent
1c91288dbc
commit
53f8871381
25
src/process.h
Normal file
25
src/process.h
Normal 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
|
||||
132
src/server.c
132
src/server.c
@ -1,10 +1,116 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.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[]) {
|
||||
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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user