159 lines
5.6 KiB
C
159 lines
5.6 KiB
C
// SPDX-License-Identifier: MIT
|
|
/*
|
|
* proc_stat_parse - turn /proc/N/stat into human-readable form
|
|
* written by Jan Engelhardt, 2012
|
|
*/
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <libHX/init.h>
|
|
#include <libHX/string.h>
|
|
|
|
struct sp_task {
|
|
char comm[32], state;
|
|
int pid, ppid, pgid, sid, tty_nr, tty_pgrp;
|
|
unsigned int task_flags;
|
|
/*
|
|
* We have to use unsigned long long here, since the kernel's unsigned
|
|
* long may be longer than userspace's.
|
|
*/
|
|
unsigned long long min_flt, cmin_flt, max_flt, cmax_flt;
|
|
long long utime, stime, cutime, cstime;
|
|
int priority, nice, num_threads;
|
|
unsigned long long start_time, vsize, get_mm_rss, rsslim;
|
|
unsigned long long mm_start_code, mm_end_code, mm_start_stack;
|
|
unsigned long long sp, ip, sig_pend, sig_block, sig_ign, sig_catch;
|
|
unsigned long long wchan;
|
|
int exit_signal, task_cpu;
|
|
unsigned int task_rt_prio, task_policy;
|
|
unsigned long long da_blkio_ticks, gtime, cgtime, start_data;
|
|
unsigned long long end_data, start_brk;
|
|
};
|
|
|
|
static void sp_init_task(struct sp_task *p)
|
|
{
|
|
memset(p, 0, sizeof(*p));
|
|
}
|
|
|
|
static void sp_interp_line(const char *s)
|
|
{
|
|
struct sp_task t;
|
|
|
|
sp_init_task(&t);
|
|
sscanf(s,/*1 */ "%d %31s %c %d %d "
|
|
/* 6 */ "%d %d %d %u %llu "
|
|
/* 11 */ "%llu %llu %llu %llu %llu "
|
|
/* 16 */ "%llu %llu %d %d %d "
|
|
/* 21 */ "0 %llu %llu %llu %llu "
|
|
/* 26 */ "%llu %llu %llu %llu %llu "
|
|
/* 31 */ "%llu %llu %llu %llu %llu "
|
|
/* 36 */ "0 0 %d %d %u "
|
|
/* 41 */ "%u %llu %llu %lld %llu "
|
|
/* 46 */ "%llu %llu",
|
|
/* 1 */ &t.pid, t.comm, &t.state, &t.ppid, &t.pgid,
|
|
/* 6 */ &t.sid, &t.tty_nr, &t.tty_pgrp, &t.task_flags, &t.min_flt,
|
|
/* 11 */ &t.cmin_flt, &t.max_flt, &t.cmax_flt, &t.utime, &t.stime,
|
|
/* 16 */ &t.cutime, &t.cstime, &t.priority, &t.nice, &t.num_threads,
|
|
/* 21 */ /*,*/ &t.start_time, &t.vsize, &t.get_mm_rss, &t.rsslim,
|
|
/* 26 */ &t.mm_start_code, &t.mm_end_code, &t.mm_start_stack, &t.sp, &t.ip,
|
|
/* 31 */ &t.sig_pend, &t.sig_block, &t.sig_ign, &t.sig_catch, &t.wchan,
|
|
/* 36 */ /*,,*/ &t.exit_signal, &t.task_cpu, &t.task_rt_prio,
|
|
/* 41 */ &t.task_policy, &t.da_blkio_ticks, &t.gtime, &t.cgtime, &t.start_data,
|
|
/* 46 */ &t.end_data, &t.start_brk
|
|
);
|
|
printf("01 PID: %d\n", t.pid);
|
|
printf("02 Comm: %s\n", t.comm);
|
|
printf("03 State: %c\n", t.state);
|
|
printf("04 PPID: %d\n", t.ppid);
|
|
printf("05 PGID: %d\n", t.pgid);
|
|
printf("06 SID: %d\n", t.sid);
|
|
printf("07 tty_nr: %d\n", t.tty_nr);
|
|
printf("08 tty_pgrp: %d\n", t.tty_pgrp);
|
|
printf("09 task_flags: 0x%x\n", t.task_flags);
|
|
printf("10 min_flt: %llu\n", t.min_flt);
|
|
printf("11 cmin_flt: %llu\n", t.cmin_flt);
|
|
printf("12 max_flt: %llu\n", t.max_flt);
|
|
printf("13 cmax_flt: %llu\n", t.cmax_flt);
|
|
printf("14 utime: %lld clocks (= %lld s)\n",
|
|
t.utime, t.utime / CLOCKS_PER_SEC);
|
|
printf("15 stime: %lld clocks (= %lld s)\n",
|
|
t.stime, t.stime / CLOCKS_PER_SEC);
|
|
printf("16 cutime: %lld clocks (= %lld s)\n",
|
|
t.cutime, t.cutime / CLOCKS_PER_SEC);
|
|
printf("17 cstime: %lld clocks (= %lld s)\n",
|
|
t.cstime, t.cstime / CLOCKS_PER_SEC);
|
|
printf("18 priority: %d\n", t.priority);
|
|
printf("19 nice: %d\n", t.nice);
|
|
printf("20 num_threads: %d\n", t.num_threads);
|
|
printf("21 -- always 0\n");
|
|
printf("22 start_time: %llu\n", t.start_time);
|
|
printf("23 vsize: 0x%llx (%llu)\n", t.vsize, t.vsize);
|
|
printf("24 get_mm_rss: 0x%llx (%llu)\n", t.get_mm_rss, t.get_mm_rss);
|
|
printf("25 rsslim: 0x%llx (%llu)\n", t.rsslim, t.rsslim);
|
|
printf("26 mm_start_code: 0x%llx\n", t.mm_start_code);
|
|
printf("27 mm_end_code: 0x%llx\n", t.mm_end_code);
|
|
printf("28 mm_start_stack: 0x%llx\n", t.mm_start_stack);
|
|
printf("29 sp register: 0x%llx\n", t.sp);
|
|
printf("30 ip register: 0x%llx\n", t.ip);
|
|
printf("31 obsol-sig-pend: 0x%llx\n", t.sig_pend);
|
|
printf("32 obsol-sig-block: 0x%llx\n", t.sig_block);
|
|
printf("33 obsol-sig-ign: 0x%llx\n", t.sig_ign);
|
|
printf("34 obsol-sig-catch: 0x%llx\n", t.sig_catch);
|
|
printf("35 wchan: 0x%llx\n", t.wchan);
|
|
printf("36 -- always 0\n");
|
|
printf("37 -- always 0\n");
|
|
printf("38 task_exit_sig: %d\n", t.exit_signal);
|
|
printf("39 task_cpu: %d\n", t.task_cpu);
|
|
printf("40 task_rt_prio: %u\n", t.task_rt_prio);
|
|
printf("41 task_policy: %u\n", t.task_policy);
|
|
printf("42 delayacct_blkio: %llu ticks\n", t.da_blkio_ticks);
|
|
printf("43 gtime: %lld clocks (= %lld s)\n",
|
|
t.gtime, t.gtime / CLOCKS_PER_SEC);
|
|
printf("44 cgtime: %lld clocks (= %lld s)\n",
|
|
t.cgtime, t.cgtime / CLOCKS_PER_SEC);
|
|
printf("45 start_data: 0x%llx\n", t.start_data);
|
|
printf("46 end_data: 0x%llx\n", t.end_data);
|
|
printf("47 start_brk: 0x%llx\n", t.start_brk);
|
|
}
|
|
|
|
static void sp_interp_file(FILE *fp)
|
|
{
|
|
hxmc_t *line = NULL;
|
|
|
|
while (HX_getl(&line, fp) != NULL)
|
|
sp_interp_line(line);
|
|
|
|
HXmc_free(line);
|
|
}
|
|
|
|
int main(int argc, const char **argv)
|
|
{
|
|
const char *prog = argv[0];
|
|
int ret;
|
|
|
|
ret = HX_init();
|
|
if (ret <= 0) {
|
|
fprintf(stderr, "%s: HX_init: %s\n", prog, strerror(-ret));
|
|
return EXIT_FAILURE;
|
|
}
|
|
if (argc == 1) {
|
|
sp_interp_file(stdin);
|
|
HX_exit();
|
|
return EXIT_SUCCESS;
|
|
}
|
|
while (*++argv != NULL) {
|
|
FILE *fp = fopen(*argv, "r");
|
|
if (fp == NULL) {
|
|
fprintf(stderr, "%s: %s: %s\n",
|
|
prog, *argv, strerror(errno));
|
|
continue;
|
|
}
|
|
sp_interp_file(fp);
|
|
fclose(fp);
|
|
}
|
|
HX_exit();
|
|
return EXIT_SUCCESS;
|
|
}
|