On Fri Feb 12 18:04:55 2010, SREZIC wrote:
Show quoted text> On Mon Jan 09 12:24:24 2006, guest wrote:
> > Running the sample script provided does work, however some fields do
> > not contain useful information, Likely beacuse of a change in the OS:
> [...]
>
> Indeed, in FreeBSD 6.0 the format of /proc/.../status changed. Attached
> are two patches. One is fixing the always broken microsecs calculation,
> and the second is fixing the changed procfs format, but still retaining
> the old pre-6.0 implementation.
Here's an amendment to the previous patch files. Please use only this
one. This patch includes the following changes for FreeBSD:
- use kvm implementation as default for FreeBSD 5.x and newer (because
procfs is not anymore mounted by default)
- fixes in the kvm implementation:
- fixed start time if microsecs < 100000
- enhancements in the kvm implementation:
- support for user and system time
- using FreeBSD-kvm is possible now without any special permissions
- fixes in the procfs implementation:
- support for FreeBSD 6.x and later
- fixed all fields with microsecs
Regards,
Slaven
diff --git c/README.freebsd w/README.freebsd
deleted file mode 100644
index 4da4431..0000000
--- c/README.freebsd
+++ /dev/null
@@ -1,23 +0,0 @@
-SUPPORTED ATTRIBUTES
-====================
- uid UID of process
- gid GID of process
- euid effective UID of process
- egid effective GID of process
- pid process ID
- ppid parent process ID
- pgrp process group
- sess session ID
- priority priority of process
- ttynum tty number of process
- flags flags of process
- utime user mode time
- stime kernel mode time
- time user + system time
- wchan address of current system call
- fname file name
- start start time (seconds since the epoch)
- state state of process
- ttydev path of process's tty
- cmndline full command line of process
- priority priority of process
diff --git c/README.freebsd-kvm w/README.freebsd-kvm
index 470f161..4c0ec09 100644
--- c/README.freebsd-kvm
+++ w/README.freebsd-kvm
@@ -12,6 +12,8 @@ SUPPORTED ATTRIBUTES
sflags PS_* flags
start start time
time running time (in seconds)
+ utime user time (in seconds)
+ stime system time (in seconds)
wchan current system call
state state of process
@@ -36,8 +38,6 @@ its use is not recommended in future. In addition, mapping processes space
to /proc is not correct (at least, in 7 of 7 my freebsd servers with
FreeBSD5 installed).
-So, I decided to write this code. This module works via kvm system, all its
-need is access to /dev/mem and /dev/kmem (you can add user to kmem group
-in /etc/groups file).
+So, I decided to write this code. This module works via the kvm system.
Any comments please send to king2@kaluga.ru.
diff --git c/README.freebsd-procfs w/README.freebsd-procfs
new file mode 100644
index 0000000..4da4431
--- /dev/null
+++ w/README.freebsd-procfs
@@ -0,0 +1,23 @@
+SUPPORTED ATTRIBUTES
+====================
+ uid UID of process
+ gid GID of process
+ euid effective UID of process
+ egid effective GID of process
+ pid process ID
+ ppid parent process ID
+ pgrp process group
+ sess session ID
+ priority priority of process
+ ttynum tty number of process
+ flags flags of process
+ utime user mode time
+ stime kernel mode time
+ time user + system time
+ wchan address of current system call
+ fname file name
+ start start time (seconds since the epoch)
+ state state of process
+ ttydev path of process's tty
+ cmndline full command line of process
+ priority priority of process
diff --git c/hints/freebsd.pl w/hints/freebsd.pl
old mode 100644
new mode 100755
index 28a5b27..a18a0be
--- c/hints/freebsd.pl
+++ w/hints/freebsd.pl
@@ -1 +1,11 @@
-symlink "os/FreeBSD.c", "OS.c" || die "Could not link os/FreeBSD.c to os/OS.c\n";
+require Config;
+my($maj) = $Config::Config{osvers} =~ m{^(\d+)};
+if ($maj < 5) {
+ print STDERR "Using procfs implementation\n";
+ symlink "os/FreeBSD.c", "OS.c" || die "Could not link os/FreeBSD.c to os/OS.c\n";
+} else {
+ print STDERR "Using kvm implementation\n";
+ symlink "os/FreeBSD-kvm.c", "OS.c" || die "Could not link os/FreeBSD-kvm.c to os/OS.c\n";
+ $self->{LIBS} = ['-lkvm'];
+}
+
diff --git c/hints/freebsd_5.pl w/hints/freebsd_5.pl
deleted file mode 100644
index aeee53b..0000000
--- c/hints/freebsd_5.pl
+++ /dev/null
@@ -1,2 +0,0 @@
-symlink "os/FreeBSD-kvm.c", "OS.c" || die "Could not link os/FreeBSD-kvm.c to os/OS.c\n";
-$self->{LIBS} = ['-lkvm'];
diff --git c/os/FreeBSD-kvm.c w/os/FreeBSD-kvm.c
index bc7f6f6..43c2611 100644
--- c/os/FreeBSD-kvm.c
+++ w/os/FreeBSD-kvm.c
@@ -2,8 +2,11 @@
#include <unistd.h>
#include <sys/sysctl.h>
#include <sys/proc.h>
+#include <sys/times.h>
#include <sys/user.h>
+#include <fcntl.h>
#include <kvm.h>
+#include <paths.h>
@@ -24,6 +27,8 @@ void OS_get_table(){
char state[20];
char start[20];
char time[20];
+ char utime[20];
+ char stime[20];
char flag[20];
char sflag[20];
@@ -32,7 +37,7 @@ void OS_get_table(){
int priority;
/* Open the kvm interface, get a descriptor */
- if ((kd = kvm_open(NULL, NULL, NULL, 0, errbuf)) == NULL) {
+ if ((kd = kvm_openfiles(_PATH_DEVNULL, _PATH_DEVNULL, NULL, O_RDONLY, errbuf)) == NULL) {
fprintf(stderr, "kvm_open: %s\n", errbuf);
ppt_croak("kvm_open: ", errbuf);
}
@@ -92,8 +97,10 @@ void OS_get_table(){
}
- sprintf(start, "%d.%d", procs[i].ki_start.tv_sec, procs[i].ki_start.tv_usec);
+ sprintf(start, "%d.%06d", procs[i].ki_start.tv_sec, procs[i].ki_start.tv_usec);
sprintf(time, "%.6f", procs[i].ki_runtime/1000000.0);
+ sprintf(utime, "%d.%06d", procs[i].ki_rusage.ru_utime.tv_sec, procs[i].ki_rusage.ru_utime.tv_usec);
+ sprintf(stime, "%d.%06d", procs[i].ki_rusage.ru_stime.tv_sec, procs[i].ki_rusage.ru_stime.tv_usec);
sprintf(flag, "0x%04x", procs[i].ki_flag);
sprintf(sflag, "0x%04x", procs[i].ki_sflag);
@@ -113,6 +120,8 @@ void OS_get_table(){
start,
time,
+ utime,
+ stime,
procs[i].ki_wmesg,
state,
diff --git c/os/FreeBSD-kvm.h w/os/FreeBSD-kvm.h
index bda9364..ca16153 100644
--- c/os/FreeBSD-kvm.h
+++ w/os/FreeBSD-kvm.h
@@ -13,7 +13,7 @@
/* We need to pass in a cap for ignore, lower for store on object */
/* We can just lc these! */
-static char Defaultformat[] = "iiiiiiisssssssissiiiiiii";
+static char Defaultformat[] = "iiiiiiisssssssssissiiiiiii";
/* Mapping of field to type */
static char* Fields[] = {
@@ -29,6 +29,8 @@ static char* Fields[] = {
"sflags",
"start",
"time",
+ "utime",
+ "stime",
"wchan",
"state",
diff --git c/os/FreeBSD.c w/os/FreeBSD.c
index 08b0919..a4b2cac 100644
--- c/os/FreeBSD.c
+++ w/os/FreeBSD.c
@@ -8,14 +8,22 @@ struct procstat* get_procstat( char* path, struct procstat* prs){
if( (fp = fopen( path, "r" )) != NULL ){
fscanf(fp,
+#ifdef PROCFS_FREEBSD_6
+ "%s %d %d %d %d %s %s %d,%d %d,%d %d,%d %s %d %d %d,%d,%s",
+#else
"%s %d %d %d %d %d,%d %s %d,%d %d,%d %d,%d %s %d %d %d,%d,%s",
+#endif
&prs->comm,
&prs->pid,
&prs->ppid,
&prs->pgid,
&prs->sid,
+#ifdef PROCFS_FREEBSD_6
+ &prs->ttydev,
+#else
&prs->tdev_maj,
&prs->tdev_min,
+#endif
&prs->flags,
&prs->start,
&prs->start_mic,
@@ -93,20 +101,33 @@ void OS_get_table(){
double start_f;
char *ttydev;
int ttynum;
+#ifdef PROCFS_FREEBSD_6
+ struct stat tdev_stat;
+#endif
- utime_f = prs.utime + prs.utime_mic/1000000;
- stime_f = prs.stime + prs.stime_mic/1000000;
+ utime_f = prs.utime + prs.utime_mic/1000000.0;
+ stime_f = prs.stime + prs.stime_mic/1000000.0;
time_f = utime_f + stime_f;
- start_f = prs.start + prs.start_mic/1000000;
+ start_f = prs.start + prs.start_mic/1000000.0;
sprintf(utime, "%f", utime_f);
sprintf(stime, "%f", stime_f);
sprintf(time, "%f", time_f);
sprintf(start, "%f", start_f);
+#ifdef PROCFS_FREEBSD_6
+ ttydev = prs.ttydev;
+ sprintf(pathbuf, "/dev/%s", ttydev);
+ if (stat(pathbuf, &tdev_stat) < 0){
+ ttynum = -1;
+ } else {
+ ttynum = tdev_stat.st_rdev;
+ }
+#else
ttynum = makedev(prs.tdev_maj, prs.tdev_min);
ttydev = devname(ttynum, S_IFCHR);
if (ttydev == NULL) ttydev = "??";
+#endif
/* get stuff out of /proc/PROC_ID/cmdline */
sprintf(pathbuf, "%s%s%s", "/proc/", procdirp->d_name, "/cmdline");
diff --git c/os/FreeBSD.h w/os/FreeBSD.h
index 85b5117..4b6fca5 100644
--- c/os/FreeBSD.h
+++ w/os/FreeBSD.h
@@ -11,14 +11,25 @@
#include <stdlib.h>
#include <string.h>
+#if __FreeBSD_version >= 600000
+/* in FreeBSD 6.x the format of /proc/$pid/status changed */
+#define PROCFS_FREEBSD_6
+#else
+#undef PROCFS_FREEBSD_6
+#endif
+
struct procstat {
char comm[MAXCOMLEN+1];
int pid;
int ppid;
int pgid;
int sid;
+#ifdef PROCFS_FREEBSD_6
+ char ttydev[SPECNAMELEN];
+#else
int tdev_maj;
int tdev_min;
+#endif
char flags[256]; /* XXX */
int start;
int start_mic;
@@ -102,3 +113,4 @@ static char* Fields[] = {
#define F_LASTFIELD 19
};
+