Added code to read status and io files

This commit is contained in:
Dan Snyder 2025-01-14 00:34:50 -05:00
parent 341a1228aa
commit 0068c483fc
3 changed files with 135 additions and 58 deletions

39
py/stat_flags.py Normal file
View File

@ -0,0 +1,39 @@
reverse_lookup = {
0x00000001: "PF_VCPU", # I'm a virtual CPU
0x00000002: "PF_IDLE", # I am an IDLE thread
0x00000004: "PF_EXITING", # Getting shut down
0x00000008: "PF_POSTCOREDUMP", # Coredumps should ignore this task
0x00000010: "PF_IO_WORKER", # Task is an IO worker
0x00000020: "PF_WQ_WORKER", # I'm a workqueue worker
0x00000040: "PF_FORKNOEXEC", # Forked but didn't exec
0x00000080: "PF_MCE_PROCESS", # Process policy on mce errors
0x00000100: "PF_SUPERPRIV", # Used super-user privileges
0x00000200: "PF_DUMPCORE", # Dumped core
0x00000400: "PF_SIGNALED", # Killed by a signal
0x00000800: "PF_MEMALLOC", # Allocating memory
0x00001000: "PF_NPROC_EXCEEDED", # set_user() noticed that RLIMIT_NPROC was exceeded
0x00002000: "PF_USED_MATH", # If unset the fpu must be initialized before use
0x00004000: "PF_USER_WORKER", # Kernel thread cloned from userspace thread
0x00008000: "PF_NOFREEZE", # This thread should not be frozen
0x00010000: "PF__HOLE__00010000",
0x00020000: "PF_KSWAPD", # I am kswapd
0x00040000: "PF_MEMALLOC_NOFS", # All allocation requests will inherit GFP_NOFS
0x00080000: "PF_MEMALLOC_NOIO", # All allocation requests will inherit GFP_NOIO
0x00100000: "PF_LOCAL_THROTTLE", # Throttle writes only against the bdi I write to, I am cleaning dirty pages from some other bdi.
0x00200000: "PF_KTHREAD", # I am a kernel thread
0x00400000: "PF_RANDOMIZE", # Randomize virtual address space
0x00800000: "PF__HOLE__00800000",
0x01000000: "PF__HOLE__01000000",
0x02000000: "PF__HOLE__02000000",
0x04000000: "PF_NO_SETAFFINITY", # Userland is not allowed to meddle with cpus_mask
0x08000000: "PF_MCE_EARLY", # Early kill for mce process policy
0x10000000: "PF_MEMALLOC_PIN", # Allocation context constrained to zones which allow long term pinning.
0x20000000: "PF__HOLE__20000000",
0x40000000: "PF__HOLE__40000000",
0x80000000: "PF_SUSPEND_TASK", # This thread called freeze_processes() and should not be frozen
}
def listFlags(flag):
for i in reverse_lookup.keys():
if flag & i:
print(reverse_lookup[i])

View File

@ -14,13 +14,16 @@ typedef struct st_process {
int ppid;
int tgid;
int level;
char *label;
char label[128];
int iskernel;
// statistics - each outputs 1 line per process
uint64_t cpuTime;
uint64_t childCpuTime;
uint64_t nThreads;
uint64_t resident;
uint64_t swap;
uint64_t written;
uint64_t read;
} Process;
#endif

View File

@ -65,28 +65,17 @@ int parseStatFile(Process *proc, char *filedata) {
proc->ppid = fast_str2ull(&location);
location += 1;
// (5) pgrp - %d
proc->tgid = fast_str2ll(&location);
location += 1;
if (proc->tgid && proc->tgid != proc->pid) return -1;
// (6) session - %d
location = strchr(location, ' ') + 1;
// skip [7 - 14)
//skipRange(7,14);
skipRange(7, 9);
// skip [5 - 9)
skipRange(5, 9);
// (9) flags - %u
proc->flags = fast_str2ull(&location);
location += 1;
printf("Flags for %d: %u %d\n", proc->pid, proc->flags, proc->flags & PF_KTHREAD);
proc->iskernel = (proc->flags & PF_KTHREAD) ? true : false;
location += 1;
//skipRange(10, 14);
// skip [10 - 14)
skipRange(10, 14);
// (14) utime - %lu
proc->cpuTime = fast_str2ull(&location);
@ -107,34 +96,45 @@ int parseStatFile(Process *proc, char *filedata) {
// skip 18-19
skipRange(18, 20);
// (20) - num_threads %ld
// (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[]) {
inline int findAndParseField(char **filedata, char *fld) {
char *field = strstr(filedata, fld);
while (*(++field) != ':');
while (*(++field) == ' ');
*filedata = field;
return fast_str2ull(filedata);
}
int parseStatusFile(Process *proc, char *filedata) {
proc->pid = findAndParseField(&filedata, "Pid");
proc->tgid = findAndParseField(&filedata, "Tgid");
if (proc->pid != proc->tgid) return -1; // ignore child threads, as their stats are the same as the parent
proc->resident = 1024 * findAndParseField(&filedata, "VmRSS");
proc->swap = 1024 * findAndParseField(&filedata, "VmSwap");
}
int parseIOFile(Process *proc, char *filedata) {
proc->read = findAndParseField(&filedata, "read_bytes");
proc->written = findAndParseField(&filedata, "write_bytes");
return 0;
}
char *readProcesses(char *procdir) {
int len, rc = 1;
struct dirent *pDirent;
DIR *pDir;
// Ensure correct argument count.
if (argc != 2) {
printf("Usage: testprog <dirname>\n");
return 1;
}
// Ensure we can open directory.
pDir = opendir(argv[1]);
pDir = opendir(procdir);
if (pDir == NULL) {
printf("Cannot open directory '%s'\n", argv[1]);
return 1;
@ -144,35 +144,48 @@ int main(int argc, char *argv[]) {
char *buffer = malloc(4096);
char *fname = malloc(1024);
char first;
FILE *file;
Process *cur = malloc(sizeof(Process));
cur->label = malloc(256);
cur->prev = NULL;
cur->next = NULL;
Process *head = cur;
while ((pDirent = readdir(pDir)) != NULL) {
char first = pDirent->d_name[0];
first = pDirent->d_name[0];
if (first < '0' || first > '9') continue;
sprintf(fname, "/proc/%s/stat", pDirent->d_name);
sprintf(fname, "/proc/%s/status", pDirent->d_name);
file = fopen(fname, "rb");
if (file == NULL) continue;
fread(buffer, 1, 4096, file);
fclose(file);
if (parseStatusFile(cur, buffer)) continue;
// truncate 'status' to 'stat'
len = strlen(fname);
fname[len-2] = 0;
file = fopen(fname, "rb");
if (file == NULL) continue;
fread(buffer, 1, 4096, file);
fclose(file);
if (parseStatFile(cur, buffer)) 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");
if (file == NULL) continue;
fread(buffer, 1, 4096, file);
fclose(file);
strtok(buffer, "\n");
if (parseIOFile(cur, buffer)) continue;
cur->next = malloc(sizeof(Process));
cur->next->prev = cur;
cur = cur->next;
}
closedir(pDir);
// clean up unused last node
cur = cur->prev;
free(cur->next);
cur->next = NULL;
@ -183,17 +196,33 @@ int main(int argc, char *argv[]) {
while (cur != NULL) {
// create process descriptor
sprintf(buffer, "pid=\"%d\",ppid=\"%d\",label=\"%s\",kernel=\"%d\"", cur->pid, cur->ppid, cur->label, cur->iskernel);
printf("proc_cpu_time{%s} %d\n", buffer, cur->cpuTime);
printf("proc_child_cpu_time{%s} %d\n", buffer, cur->childCpuTime / clocks);
printf("proc_num_threads{%s} %d\n", buffer, cur->nThreads);
printf("proc_resident_bytes{%s} %d\n", buffer, cur->resident);
printf("proc_cpu_time{%s} %lf\n", buffer, (double) cur->cpuTime / clocks);
printf("proc_child_cpu_time{%s} %lf\n", buffer, (double) cur->childCpuTime / clocks);
printf("proc_num_threads{%s} %llu\n", buffer, cur->nThreads);
printf("proc_resident_bytes{%s} %llu\n", buffer, cur->resident);
printf("proc_swap_bytes{%s} %llu\n", buffer, cur->swap);
printf("proc_fileio_bytes_written{%s} %llu\n", buffer, cur->written);
printf("proc_fileio_bytes_read{%s} %llu\n", buffer, cur->read);
cur = cur->next;
}
return 0;
rc = 0;
freeChain:
cur = head;
while (cur != NULL) {
Process *prev = cur;
cur = cur->next;
free(prev);
}
#define PORT 8080
closedir(pDir);
free(buffer);
free(fname);
return rc;
}
#define PORT 9101
#define BUFFER_SIZE 1024
void handle_client(int client_socket) {
@ -201,10 +230,10 @@ void handle_client(int client_socket) {
const char *http_response =
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/plain\r\n"
"Content-Length: 13\r\n"
"Content-Length: 25\r\n"
"Connection: close\r\n"
"\r\n"
"Hello, World!";
"test{data=\"something\"} 25";
// Send the response to the client
send(client_socket, http_response, strlen(http_response), 0);
@ -213,7 +242,13 @@ void handle_client(int client_socket) {
close(client_socket);
}
int main2() {
int main(int argc, char *argv[]) {
if (argc == 1) {
readProcesses("/proc");
return;
}
int server_socket, client_socket;
struct sockaddr_in server_addr, client_addr;
socklen_t addr_len = sizeof(client_addr);