Hello !
I'm trying to solve
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=676450 . All I need
before submitting a first attempt at the Hurd backend to the
python-psutil folks is to be able to retrieve data similar to what can
be found in /proc/stat on GNU/Linux (without using the procfs
translator, obviously).
Here is an extract of "man 5 proc" on Debian GNU/Linux:
"/proc/stat
kernel/system statistics. Varies with architecture. Common
entries include:
cpu 3357 0 4313 1362393
The amount of time, measured in units of USER_HZ (1/100ths
of a second on most architectures, use sysconf(_SC_CLK_TCK) to obtain
the right value), that the system spent in user mode,
user mode with low priority (nice), system mode, and the idle task,
respectively. The last value should be USER_HZ times the second entry in
the uptime pseudo-file."
I thought that one way of doing this would be to apply the following
algorithm:
total_system_time := 0
total_user_time := 0
processes := list_all_processes()
for p in processes:
total_system_time += p.system_time
total_user_time += p.user_time
I've tried three different things:
1) using the getters defined in libps/spec.c
2) using proc_getprocinfo()
3) using task_info()
Here are the resutls I get :
$ ./getter && ./procinfo && ./task_info
System 1900, User 300
System 192000, User 300
System 0, User 0
$ head -1 /proc/stat
cpu 2884 0 0 195460 0 0 0 0 0
What is the right method ? What am I doing wrong ? Attached are the
three source files I used.
Cyril Roelandt.
#define _GNU_SOURCE
#include <hurd.h>
#include <ps.h>
#include <sys/time.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
int
main(void)
{
int err;
mach_port_t proc = getproc();
pid_t *pids = NULL;
mach_msg_type_number_t pidslen = 0;
struct timeval tot_sys = { 0, 0 };
struct timeval tot_usr = { 0, 0 };
err = proc_getallpids(proc, &pids, &pidslen);
assert(err == 0);
struct ps_context *pc = NULL;
err = ps_context_create(getproc(), &pc);
assert(err == 0 && pc != NULL);
unsigned i;
for (i = 0; i < pidslen; i++)
{
struct proc_stat *ps = NULL;
err = ps_context_find_proc_stat(pc, pids[i], &ps);
assert(err == 0 && ps != NULL);
const struct ps_fmt_spec *sys_spec = NULL;
sys_spec = ps_fmt_specs_find(&ps_std_fmt_specs, "STime");
assert(sys_spec != NULL);
const struct ps_getter *sys_getter = NULL;
sys_getter = sys_spec->getter;
assert(sys_getter != NULL);
const struct ps_fmt_spec *usr_spec = NULL;
usr_spec = ps_fmt_specs_find(&ps_std_fmt_specs, "UTime");
assert(usr_spec != NULL);
const struct ps_getter *usr_getter = NULL;
usr_getter = usr_spec->getter;
assert(usr_getter != NULL);
ps_flags_t sys_needs = ps_getter_needs(sys_getter);
ps_flags_t usr_needs = ps_getter_needs(usr_getter);
err = proc_stat_set_flags(ps, sys_needs);
assert(err == 0 && (ps->flags & sys_needs));
err = proc_stat_set_flags(ps, usr_needs);
assert(err == 0 && (ps->flags & usr_needs));
/* Finally getting the values we are looking for. */
struct timeval sys_val;
struct timeval usr_val;
sys_getter->fn(ps, &sys_val);
usr_getter->fn(ps, &usr_val);
timeradd(&sys_val, &tot_sys, &tot_sys);
timeradd(&usr_val, &tot_usr, &tot_usr);
}
/* Convert to jiffies before printing. */
//long clock_ticks = sysconf("_SC_CLK_TCK");
long clock_ticks = 100;
fprintf(stderr, "System %ld, User %ld\n",
tot_sys.tv_sec * clock_ticks,
tot_usr.tv_sec * clock_ticks);
return 0;
}
#define _GNU_SOURCE
#include <hurd.h>
#include <ps.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
int
main(void)
{
struct timeval sys = { 0, 0 };
struct timeval usr = { 0, 0 };
mach_port_t proc = getproc();
pid_t *pids = NULL;
mach_msg_type_number_t pidslen = 0;
error_t err;
err = proc_getallpids (proc, &pids, &pidslen);
unsigned i;
for (i = 0; i < pidslen; i++)
{
int pi_flags = PI_FETCH_TASKINFO | PI_FETCH_THREADS |
PI_FETCH_THREAD_BASIC;
struct ps_context *pc = NULL;
err = ps_context_create(getproc(), &pc);
assert(err == 0 && pc != NULL);
struct proc_stat *ps = NULL;
err = ps_context_find_proc_stat(pc, pids[i], &ps);
assert(err == 0 && ps != NULL);
size_t pi_size = ps->proc_info_size;
size_t waits_len = ps->thread_waits_len;
err = proc_getprocinfo(
getproc(),
pids[i],
&pi_flags,
(procinfo_t *) &ps->proc_info,
&pi_size,
&ps->thread_waits,
&waits_len);
struct procinfo *pi = ps->proc_info;
int j;
for (j = 0; j < pi->nthreads; j++)
{
struct timeval tmp;
thread_basic_info_t tbi = &pi->threadinfos[j].pis_bi;
tmp.tv_sec = tbi->system_time.seconds;
tmp.tv_usec = tbi->system_time.microseconds;
timeradd(&tmp, &sys, &sys);
tmp.tv_sec = tbi->user_time.seconds;
tmp.tv_usec = tbi->user_time.microseconds;
timeradd(&tmp, &usr, &usr);
}
}
fprintf(stderr, "System %ld, User %ld\n",
sys.tv_sec * 100,
usr.tv_sec * 100);
return 0;
}
#define _GNU_SOURCE
#include <hurd.h>
#include <ps.h>
#include <sys/time.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
int
main(void)
{
struct timeval tot_sys = { 0, 0 };
struct timeval tot_usr = { 0, 0 };
mach_port_t proc = getproc();
pid_t *pids = NULL;
mach_msg_type_number_t pidslen = 0;
assert(proc_getallpids (proc, &pids, &pidslen) == 0);
unsigned i;
for (i = 0; i < pidslen; i++)
{
error_t err;
struct ps_context *pc = NULL;
err = ps_context_create(getproc(), &pc);
assert(err == 0 && pc != NULL);
struct proc_stat *ps = NULL;
err = ps_context_find_proc_stat(pc, pids[i], &ps);
assert(err == 0 && ps != NULL);
struct task_thread_times_info ttti;
ttti.user_time.seconds = 0;
ttti.user_time.microseconds = 0;
ttti.system_time.seconds = 0;
ttti.system_time.microseconds = 0;
mach_msg_type_number_t cnt = TASK_THREAD_TIMES_INFO_COUNT;
kern_return_t error;
proc_stat_set_flags(ps, PSTAT_TASK | PSTAT_TASK_BASIC);
error = task_info(ps->task, TASK_THREAD_TIMES_INFO,
(task_info_t) &ttti, &cnt);
if (error == KERN_SUCCESS)
{
struct timeval tmp;
tmp.tv_sec = ttti.user_time.seconds;
tmp.tv_usec = ttti.user_time.microseconds;
timeradd(&tmp, &tot_usr, &tot_usr);
tmp.tv_sec = ttti.system_time.seconds;
tmp.tv_usec = ttti.system_time.microseconds;
timeradd(&tmp, &tot_sys, &tot_sys);
}
struct task_basic_info tbi;
cnt = TASK_BASIC_INFO_COUNT;
error = task_info(ps->task, TASK_BASIC_INFO, (task_info_t)
&tbi, &cnt);
if (error == KERN_SUCCESS)
{
struct timeval tmp;
tmp.tv_sec = tbi.user_time.seconds;
tmp.tv_usec = tbi.user_time.microseconds;
timeradd(&tmp, &tot_usr, &tot_usr);
tmp.tv_sec = tbi.system_time.seconds;
tmp.tv_usec = tbi.system_time.microseconds;
timeradd(&tmp, &tot_sys, &tot_sys);
}
}
fprintf(stderr, "System %ld, User %ld\n",
tot_sys.tv_sec * 100,
tot_usr.tv_sec * 100);
return 0;
}
CC=gcc
CFLAGS=-Wall -Wextra
LDFLAGS=-lps
all: getter procinfo task_info
getter: getter.c
$(CC) $(CFLAGS) $(LDFLAGS) -o getter getter.c
procinfo: procinfo.c
$(CC) $(CFLAGS) $(LDFLAGS) -o procinfo procinfo.c
task_info: task_info.c
$(CC) $(CFLAGS) $(LDFLAGS) -o task_info task_info.c
clean:
rm -f getter procinfo task_info