library: added important new functionality, <pids> api
This commit introduces some new capabilities available in libproc-2 under the <PIDS> interface. Along the way errors impacting some item values have been corrected. The following summarizes the major changes being made. 1. The PIDS_TIME_START item was represented as seconds since system boot but really held tics since boot. And some programs properly divided it by Hertz to actually yield seconds while others acted as if it already was. So, now we have a new PIDS_TICS_BEGAN field and all of the 'TIME' fields properly reflect seconds. With those 'TIME' fields, the type was changed to 'float/real' so one could convert it back to tics without loss of some centiseconds reflected in the Hertz guy (usually 100). 2. The boot_seconds was established in procps_pids_new meaning it was fixed/unchanging. As a result, one item (PIDS_TIME_ELAPSED) was rendered useless. So now, each of the three retrieval functions establishes a current boot_seconds well before the set functions are called. 3. Added a PIDS_UTILIZATION item that will provide the CPU usage over the life of a process, as a percentage. 4. Added PIDS_TIME_ALL_C for symmetry with the similar item called PIDS_TICS_ALL_C (which reflects raw tics). 5. That 'derived from' notation has been added to some additional header items to reflect their true origins. Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
parent
854e85a50b
commit
c69104b2b8
50
proc/pids.c
50
proc/pids.c
@ -90,8 +90,8 @@ struct pids_info {
|
||||
unsigned pgs2k_shift; // to convert some proc vaules
|
||||
unsigned oldflags; // the old library PROC_FILL flagss
|
||||
PROCTAB *fetch_PT; // oldlib interface for 'select' & 'reap'
|
||||
unsigned long hertz; // for TIME_ALL & TIME_ELAPSED calculations
|
||||
unsigned long long boot_seconds; // for TIME_ELAPSED calculation
|
||||
unsigned long hertz; // for the 'TIME' & 'UTILIZATION' calculations
|
||||
float boot_seconds; // for TIME_ELAPSED & 'UTILIZATION' calculations
|
||||
PROCTAB *get_PT; // oldlib interface for active 'get'
|
||||
struct stacks_extent *get_ext; // for active 'get' (also within 'extents')
|
||||
enum pids_fetch_type get_type; // last known type of 'get' request
|
||||
@ -271,6 +271,7 @@ STR_set(SUPGROUPS, supgrp)
|
||||
setDECL(TICS_ALL) { (void)I; R->result.ull_int = P->utime + P->stime; }
|
||||
setDECL(TICS_ALL_C) { (void)I; R->result.ull_int = P->utime + P->stime + P->cutime + P->cstime; }
|
||||
REG_set(TICS_ALL_DELTA, u_int, pcpu)
|
||||
REG_set(TICS_BEGAN, ull_int, start_time)
|
||||
REG_set(TICS_BLKIO, ull_int, blkio_tics)
|
||||
REG_set(TICS_GUEST, ull_int, gtime)
|
||||
setDECL(TICS_GUEST_C) { (void)I; R->result.ull_int = P->gtime + P->cgtime; }
|
||||
@ -278,12 +279,14 @@ REG_set(TICS_SYSTEM, ull_int, stime)
|
||||
setDECL(TICS_SYSTEM_C) { (void)I; R->result.ull_int = P->stime + P->cstime; }
|
||||
REG_set(TICS_USER, ull_int, utime)
|
||||
setDECL(TICS_USER_C) { (void)I; R->result.ull_int = P->utime + P->cutime; }
|
||||
setDECL(TIME_ALL) { R->result.ull_int = (P->utime + P->stime) / I->hertz; }
|
||||
setDECL(TIME_ELAPSED) { unsigned long long t = P->start_time / I->hertz; R->result.ull_int = I->boot_seconds >= t ? (I->boot_seconds - t) : 0; }
|
||||
REG_set(TIME_START, ull_int, start_time)
|
||||
setDECL(TIME_ALL) { R->result.real = ((float)P->utime + P->stime) / I->hertz; }
|
||||
setDECL(TIME_ALL_C) { R->result.real = ((float)P->utime + P->stime + P->cutime + P->cstime) / I->hertz; }
|
||||
setDECL(TIME_ELAPSED) { float t = (float)P->start_time / I->hertz; R->result.real = I->boot_seconds > t ? I->boot_seconds - t : 0; }
|
||||
setDECL(TIME_START) { R->result.real = (float)P->start_time / I->hertz; }
|
||||
REG_set(TTY, s_int, tty)
|
||||
setDECL(TTY_NAME) { char buf[64]; freNAME(str)(R); dev_to_tty(buf, sizeof(buf), P->tty, P->tid, ABBREV_DEV); if (!(R->result.str = strdup(buf))) I->seterr = 1; }
|
||||
setDECL(TTY_NUMBER) { char buf[64]; freNAME(str)(R); dev_to_tty(buf, sizeof(buf), P->tty, P->tid, ABBREV_DEV|ABBREV_TTY|ABBREV_PTS); if (!(R->result.str = strdup(buf))) I->seterr = 1; }
|
||||
setDECL(UTILIZATION) { float t; if (I->boot_seconds > 0) { t = I->boot_seconds - ((float)P->start_time / I->hertz); R->result.real = (float)P->utime + P->stime; R->result.real *= (100.0f / ((float)I->hertz * t)); }}
|
||||
REG_set(VM_DATA, ul_int, vm_data)
|
||||
REG_set(VM_EXE, ul_int, vm_exe)
|
||||
REG_set(VM_LIB, ul_int, vm_lib)
|
||||
@ -337,6 +340,8 @@ REG_srt(u_int)
|
||||
REG_srt(ul_int)
|
||||
REG_srt(ull_int)
|
||||
|
||||
REG_srt(real)
|
||||
|
||||
srtDECL(str) {
|
||||
const struct pids_result *a = (*A)->head + P->offset;
|
||||
const struct pids_result *b = (*B)->head + P->offset;
|
||||
@ -554,6 +559,7 @@ static struct {
|
||||
{ RS(TICS_ALL), f_stat, NULL, QS(ull_int), 0, TS(ull_int) },
|
||||
{ RS(TICS_ALL_C), f_stat, NULL, QS(ull_int), 0, TS(ull_int) },
|
||||
{ RS(TICS_ALL_DELTA), f_stat, NULL, QS(u_int), +1, TS(u_int) },
|
||||
{ RS(TICS_BEGAN), f_stat, NULL, QS(ull_int), 0, TS(ull_int) },
|
||||
{ RS(TICS_BLKIO), f_stat, NULL, QS(ull_int), 0, TS(ull_int) },
|
||||
{ RS(TICS_GUEST), f_stat, NULL, QS(ull_int), 0, TS(ull_int) },
|
||||
{ RS(TICS_GUEST_C), f_stat, NULL, QS(ull_int), 0, TS(ull_int) },
|
||||
@ -561,12 +567,14 @@ static struct {
|
||||
{ RS(TICS_SYSTEM_C), f_stat, NULL, QS(ull_int), 0, TS(ull_int) },
|
||||
{ RS(TICS_USER), f_stat, NULL, QS(ull_int), 0, TS(ull_int) },
|
||||
{ RS(TICS_USER_C), f_stat, NULL, QS(ull_int), 0, TS(ull_int) },
|
||||
{ RS(TIME_ALL), f_stat, NULL, QS(ull_int), 0, TS(ull_int) },
|
||||
{ RS(TIME_ELAPSED), f_stat, NULL, QS(ull_int), 0, TS(ull_int) },
|
||||
{ RS(TIME_START), f_stat, NULL, QS(ull_int), 0, TS(ull_int) },
|
||||
{ RS(TIME_ALL), f_stat, NULL, QS(real), 0, TS(real) },
|
||||
{ RS(TIME_ALL_C), f_stat, NULL, QS(real), 0, TS(real) },
|
||||
{ RS(TIME_ELAPSED), f_stat, NULL, QS(real), 0, TS(real) },
|
||||
{ RS(TIME_START), f_stat, NULL, QS(real), 0, TS(real) },
|
||||
{ RS(TTY), f_stat, NULL, QS(s_int), 0, TS(s_int) },
|
||||
{ RS(TTY_NAME), f_stat, FF(str), QS(strvers), 0, TS(str) },
|
||||
{ RS(TTY_NUMBER), f_stat, FF(str), QS(strvers), 0, TS(str) },
|
||||
{ RS(UTILIZATION), f_stat, NULL, QS(real), 0, TS(real) },
|
||||
{ RS(VM_DATA), f_status, NULL, QS(ul_int), 0, TS(ul_int) },
|
||||
{ RS(VM_EXE), f_status, NULL, QS(ul_int), 0, TS(ul_int) },
|
||||
{ RS(VM_LIB), f_status, NULL, QS(ul_int), 0, TS(ul_int) },
|
||||
@ -1198,7 +1206,6 @@ PROCPS_EXPORT int procps_pids_new (
|
||||
int numitems)
|
||||
{
|
||||
struct pids_info *p;
|
||||
double uptime_secs;
|
||||
int pgsz;
|
||||
|
||||
#ifdef ITEMTABLE_DEBUG
|
||||
@ -1282,10 +1289,6 @@ PROCPS_EXPORT int procps_pids_new (
|
||||
while (pgsz > 1024) { pgsz >>= 1; p->pgs2k_shift++; }
|
||||
p->hertz = procps_hertz_get();
|
||||
|
||||
// in case 'fatal_proc_unmounted' wasn't called and /proc isn't mounted
|
||||
if (0 >= procps_uptime(&uptime_secs, NULL))
|
||||
p->boot_seconds = uptime_secs;
|
||||
|
||||
numa_init();
|
||||
|
||||
p->fetch.results.counts = &p->fetch.counts;
|
||||
@ -1405,6 +1408,7 @@ PROCPS_EXPORT struct pids_stack *procps_pids_get (
|
||||
struct pids_info *info,
|
||||
enum pids_fetch_type which)
|
||||
{
|
||||
double up_secs;
|
||||
|
||||
errno = EINVAL;
|
||||
if (info == NULL)
|
||||
@ -1432,6 +1436,12 @@ fresh_start:
|
||||
}
|
||||
errno = 0;
|
||||
|
||||
/* when in a namespace with proc mounted subset=pid,
|
||||
we will be restricted to process information only */
|
||||
info->boot_seconds = 0;
|
||||
if (0 >= procps_uptime(&up_secs, NULL))
|
||||
info->boot_seconds = up_secs;
|
||||
|
||||
if (NULL == info->read_something(info->get_PT, &info->get_proc))
|
||||
return NULL;
|
||||
if (!pids_assign_results(info, info->get_ext->stacks[0], &info->get_proc))
|
||||
@ -1451,6 +1461,7 @@ PROCPS_EXPORT struct pids_fetch *procps_pids_reap (
|
||||
struct pids_info *info,
|
||||
enum pids_fetch_type which)
|
||||
{
|
||||
double up_secs;
|
||||
int rc;
|
||||
|
||||
errno = EINVAL;
|
||||
@ -1468,6 +1479,12 @@ PROCPS_EXPORT struct pids_fetch *procps_pids_reap (
|
||||
return NULL;
|
||||
info->read_something = which ? readeither : readproc;
|
||||
|
||||
/* when in a namespace with proc mounted subset=pid,
|
||||
we will be restricted to process information only */
|
||||
info->boot_seconds = 0;
|
||||
if (0 >= procps_uptime(&up_secs, NULL))
|
||||
info->boot_seconds = up_secs;
|
||||
|
||||
rc = pids_stacks_fetch(info);
|
||||
|
||||
pids_oldproc_close(&info->fetch_PT);
|
||||
@ -1541,6 +1558,7 @@ PROCPS_EXPORT struct pids_fetch *procps_pids_select (
|
||||
int numthese,
|
||||
enum pids_select_type which)
|
||||
{
|
||||
double up_secs;
|
||||
unsigned ids[FILL_ID_MAX + 1];
|
||||
int rc;
|
||||
|
||||
@ -1566,6 +1584,12 @@ PROCPS_EXPORT struct pids_fetch *procps_pids_select (
|
||||
return NULL;
|
||||
info->read_something = (which & PIDS_FETCH_THREADS_TOO) ? readeither : readproc;
|
||||
|
||||
/* when in a namespace with proc mounted subset=pid,
|
||||
we will be restricted to process information only */
|
||||
info->boot_seconds = 0;
|
||||
if (0 >= procps_uptime(&up_secs, NULL))
|
||||
info->boot_seconds = up_secs;
|
||||
|
||||
rc = pids_stacks_fetch(info);
|
||||
|
||||
pids_oldproc_close(&info->fetch_PT);
|
||||
|
20
proc/pids.h
20
proc/pids.h
@ -51,7 +51,7 @@ enum pids_item {
|
||||
PIDS_EXIT_SIGNAL, // s_int stat: exit_signal
|
||||
PIDS_FLAGS, // ul_int stat: flags
|
||||
PIDS_FLT_MAJ, // ul_int stat: maj_flt
|
||||
PIDS_FLT_MAJ_C, // ul_int stat: maj_flt + cmaj_flt
|
||||
PIDS_FLT_MAJ_C, // ul_int derived from stat: maj_flt + cmaj_flt
|
||||
PIDS_FLT_MAJ_DELTA, // s_int derived from FLT_MAJ
|
||||
PIDS_FLT_MIN, // ul_int stat: min_flt
|
||||
PIDS_FLT_MIN_C, // ul_int stat: min_flt + cmin_flt
|
||||
@ -154,19 +154,22 @@ enum pids_item {
|
||||
PIDS_TICS_ALL, // ull_int stat: stime + utime
|
||||
PIDS_TICS_ALL_C, // ull_int stat: stime + utime + cstime + cutime
|
||||
PIDS_TICS_ALL_DELTA, // u_int derived from TICS_ALL
|
||||
PIDS_TICS_BEGAN, // ull_int stat: start_time
|
||||
PIDS_TICS_BLKIO, // ull_int stat: blkio_ticks
|
||||
PIDS_TICS_GUEST, // ull_int stat: gtime
|
||||
PIDS_TICS_GUEST_C, // ull_int stat: gtime + cgtime
|
||||
PIDS_TICS_GUEST_C, // ull_int derived from stat: gtime + cgtime
|
||||
PIDS_TICS_SYSTEM, // ull_int stat: stime
|
||||
PIDS_TICS_SYSTEM_C, // ull_int stat: stime + cstime
|
||||
PIDS_TICS_SYSTEM_C, // ull_int derived from stat: stime + cstime
|
||||
PIDS_TICS_USER, // ull_int stat: utime
|
||||
PIDS_TICS_USER_C, // ull_int stat: utime + cutime
|
||||
PIDS_TIME_ALL, // ull_int derived from (utime + stime) / hertz
|
||||
PIDS_TIME_ELAPSED, // ull_int derived from /proc/uptime - (starttime / hertz)
|
||||
PIDS_TIME_START, // ull_int stat: start_time
|
||||
PIDS_TICS_USER_C, // ull_int derived from stat: utime + cutime
|
||||
PIDS_TIME_ALL, // real derived from (utime + stime) / hertz
|
||||
PIDS_TIME_ALL_C, // real derived from (utime + stime + cutime + cstime) / hertz
|
||||
PIDS_TIME_ELAPSED, // real derived from /proc/uptime - (starttime / hertz)
|
||||
PIDS_TIME_START, // real derived from stat: start_time / hertz
|
||||
PIDS_TTY, // s_int stat: tty_nr
|
||||
PIDS_TTY_NAME, // str derived from TTY
|
||||
PIDS_TTY_NUMBER, // str derived from TTY as str
|
||||
PIDS_UTILIZATION, // real derived from TIME_ALL / TIME_ELAPSED, as percentage
|
||||
PIDS_VM_DATA, // ul_int status: VmData
|
||||
PIDS_VM_EXE, // ul_int status: VmExe
|
||||
PIDS_VM_LIB, // ul_int status: VmLib
|
||||
@ -178,7 +181,7 @@ enum pids_item {
|
||||
PIDS_VM_SIZE, // ul_int status: VmSize
|
||||
PIDS_VM_STACK, // ul_int status: VmStk
|
||||
PIDS_VM_SWAP, // ul_int status: VmSwap
|
||||
PIDS_VM_USED, // ul_int status: VmRSS + VmSwap
|
||||
PIDS_VM_USED, // ul_int derived from status: VmRSS + VmSwap
|
||||
PIDS_VSIZE_PGS, // ul_int stat: vsize
|
||||
PIDS_WCHAN_NAME // str wchan
|
||||
};
|
||||
@ -211,6 +214,7 @@ struct pids_result {
|
||||
unsigned long long ull_int;
|
||||
char *str;
|
||||
char **strv;
|
||||
float real;
|
||||
} result;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user