sys-proctable 0.9.1-universal-freebsd
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +302 -0
- data/MANIFEST +30 -0
- data/README +120 -0
- data/Rakefile +176 -0
- data/benchmarks/bench_ps.rb +21 -0
- data/doc/top.txt +47 -0
- data/examples/example_ps.rb +20 -0
- data/ext/bsd/extconf.rb +14 -0
- data/ext/bsd/sys/proctable.c +301 -0
- data/lib/sys/top.rb +32 -0
- data/sys-proctable.gemspec +39 -0
- data/test/test_sys_proctable_all.rb +85 -0
- data/test/test_sys_proctable_bsd.rb +212 -0
- metadata +97 -0
data/Rakefile
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/clean'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rbconfig'
|
5
|
+
include Config
|
6
|
+
|
7
|
+
CLEAN.include(
|
8
|
+
'**/*.core', # Core dump files
|
9
|
+
'**/*.gem', # Gem files
|
10
|
+
'**/*.rbc', # Rubinius
|
11
|
+
'**/*.o', # C object file
|
12
|
+
'**/*.log', # Ruby extension build log
|
13
|
+
'**/Makefile', # C Makefile
|
14
|
+
'**/conftest.dSYM', # OS X build directory
|
15
|
+
"**/*.#{CONFIG['DLEXT']}" # C shared object
|
16
|
+
)
|
17
|
+
|
18
|
+
desc 'Build the sys-proctable library for C versions of sys-proctable'
|
19
|
+
task :build => [:clean] do
|
20
|
+
case Config::CONFIG['host_os']
|
21
|
+
when /bsd/i
|
22
|
+
dir = 'ext/bsd'
|
23
|
+
when /darwin/i
|
24
|
+
dir = 'ext/darwin'
|
25
|
+
when /hpux/i
|
26
|
+
dir = 'ext/hpux'
|
27
|
+
end
|
28
|
+
|
29
|
+
unless Config::CONFIG['host_os'] =~ /win32|mswin|dos|cygwin|mingw|windows|linux|sunos|solaris/i
|
30
|
+
Dir.chdir(dir) do
|
31
|
+
ruby 'extconf.rb'
|
32
|
+
sh 'make'
|
33
|
+
cp 'proctable.' + Config::CONFIG['DLEXT'], 'sys'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
desc 'Install the sys-proctable library'
|
39
|
+
task :install => [:build] do
|
40
|
+
file = nil
|
41
|
+
dir = File.join(Config::CONFIG['sitelibdir'], 'sys')
|
42
|
+
|
43
|
+
Dir.mkdir(dir) unless File.exists?(dir)
|
44
|
+
|
45
|
+
case Config::CONFIG['host_os']
|
46
|
+
when /mswin|win32|msdos|cygwin|mingw|windows/i
|
47
|
+
file = 'lib/windows/sys/proctable.rb'
|
48
|
+
when /linux/i
|
49
|
+
file = 'lib/linux/sys/proctable.rb'
|
50
|
+
when /sunos|solaris/i
|
51
|
+
file = 'lib/sunos/sys/proctable.rb'
|
52
|
+
when /bsd/i
|
53
|
+
Dir.chdir('ext/bsd'){ sh 'make install' }
|
54
|
+
when /darwin/i
|
55
|
+
Dir.chdir('ext/darwin'){ sh 'make install' }
|
56
|
+
when /hpux/i
|
57
|
+
Dir.chdir('ext/hpux'){ sh 'make install' }
|
58
|
+
end
|
59
|
+
|
60
|
+
cp(file, dir, :verbose => true) if file
|
61
|
+
end
|
62
|
+
|
63
|
+
desc 'Uninstall the sys-proctable library'
|
64
|
+
task :uninstall do
|
65
|
+
case Config::CONFIG['host_os']
|
66
|
+
when /win32|mswin|dos|cygwin|mingw|windows|linux|sunos|solaris/i
|
67
|
+
dir = File.join(Config::CONFIG['sitelibdir'], 'sys')
|
68
|
+
file = File.join(dir, 'proctable.rb')
|
69
|
+
else
|
70
|
+
dir = File.join(Config::CONFIG['sitearchdir'], 'sys')
|
71
|
+
file = File.join(dir, 'proctable.' + Config::CONFIG['DLEXT'])
|
72
|
+
end
|
73
|
+
|
74
|
+
rm(file)
|
75
|
+
end
|
76
|
+
|
77
|
+
desc 'Run the benchmark suite'
|
78
|
+
task :bench => [:build] do
|
79
|
+
sh "ruby -Ilib benchmarks/bench_ps.rb"
|
80
|
+
end
|
81
|
+
|
82
|
+
desc 'Run the example program'
|
83
|
+
task :example => [:build] do
|
84
|
+
sh 'ruby -Ilib -Iext examples/example_ps.rb'
|
85
|
+
end
|
86
|
+
|
87
|
+
desc 'Run the test suite'
|
88
|
+
Rake::TestTask.new do |t|
|
89
|
+
task :test => :build
|
90
|
+
t.libs << 'test' << '.'
|
91
|
+
|
92
|
+
case Config::CONFIG['host_os']
|
93
|
+
when /mswin|msdos|cygwin|mingw|windows/i
|
94
|
+
t.test_files = FileList['test/test_sys_proctable_windows.rb']
|
95
|
+
t.libs << 'lib/windows'
|
96
|
+
when /linux/i
|
97
|
+
t.test_files = FileList['test/test_sys_proctable_linux.rb']
|
98
|
+
t.libs << 'lib/linux'
|
99
|
+
when /sunos|solaris/i
|
100
|
+
t.test_files = FileList['test/test_sys_proctable_sunos.rb']
|
101
|
+
t.libs << 'lib/sunos'
|
102
|
+
when /darwin/i
|
103
|
+
t.libs << 'ext/darwin'
|
104
|
+
t.test_files = FileList['test/test_sys_proctable_darwin.rb']
|
105
|
+
when /bsd/i
|
106
|
+
t.libs << 'ext/bsd'
|
107
|
+
t.test_files = FileList['test/test_sys_proctable_bsd.rb']
|
108
|
+
when /hpux/i
|
109
|
+
t.libs << 'ext/hpux'
|
110
|
+
t.test_files = FileList['test/test_sys_proctable_hpux.rb']
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
namespace :gem do
|
115
|
+
desc 'Create a gem'
|
116
|
+
task :create => [:clean] do
|
117
|
+
spec = eval(IO.read('sys-proctable.gemspec'))
|
118
|
+
|
119
|
+
# I've had to manually futz with the spec here in some cases
|
120
|
+
# in order to get the universal platform settings I want because
|
121
|
+
# of some bugginess in Rubygems' platform.rb.
|
122
|
+
#
|
123
|
+
case Config::CONFIG['host_os']
|
124
|
+
when /bsd/i
|
125
|
+
spec.platform = Gem::Platform.new('universal-freebsd8.0')
|
126
|
+
spec.platform.version = nil
|
127
|
+
spec.files << 'ext/bsd/sys/proctable.c'
|
128
|
+
spec.extra_rdoc_files << 'ext/bsd/sys/proctable.c'
|
129
|
+
spec.test_files << 'test/test_sys_proctable_bsd.rb'
|
130
|
+
spec.extensions = ['ext/bsd/extconf.rb']
|
131
|
+
when /darwin/i
|
132
|
+
spec.platform = Gem::Platform.new('universal-darwin')
|
133
|
+
spec.files << 'ext/darwin/sys/proctable.c'
|
134
|
+
spec.extra_rdoc_files << 'ext/darwin/sys/proctable.c'
|
135
|
+
spec.test_files << 'test/test_sys_proctable_darwin.rb'
|
136
|
+
spec.extensions = ['ext/darwin/extconf.rb']
|
137
|
+
when /hpux/i
|
138
|
+
spec.platform = Gem::Platform.new('universal-hpux')
|
139
|
+
spec.files << 'ext/hpux/sys/proctable.c'
|
140
|
+
spec.extra_rdoc_files << 'ext/hpux/sys/proctable.c'
|
141
|
+
spec.test_files << 'test/test_sys_proctable_hpux.rb'
|
142
|
+
spec.extensions = ['ext/hpux/extconf.rb']
|
143
|
+
when /linux/i
|
144
|
+
spec.platform = Gem::Platform.new('universal-linux')
|
145
|
+
spec.require_paths = ['lib', 'lib/linux']
|
146
|
+
spec.files += ['lib/linux/sys/proctable.rb']
|
147
|
+
spec.test_files << 'test/test_sys_proctable_linux.rb'
|
148
|
+
when /sunos|solaris/i
|
149
|
+
spec.platform = Gem::Platform.new('universal-solaris10.0')
|
150
|
+
spec.platform.version = nil
|
151
|
+
spec.require_paths = ['lib', 'lib/sunos']
|
152
|
+
spec.files += ['lib/sunos/sys/proctable.rb']
|
153
|
+
spec.test_files << 'test/test_sys_proctable_sunos.rb'
|
154
|
+
when /mswin|win32|dos|cygwin|mingw|windows/i
|
155
|
+
spec.platform = Gem::Platform::CURRENT
|
156
|
+
spec.platform.cpu = 'universal'
|
157
|
+
spec.platform.version = nil
|
158
|
+
spec.require_paths = ['lib', 'lib/windows']
|
159
|
+
spec.files += ['lib/windows/sys/proctable.rb']
|
160
|
+
spec.test_files << 'test/test_sys_proctable_windows.rb'
|
161
|
+
end
|
162
|
+
|
163
|
+
# https://github.com/rubygems/rubygems/issues/147
|
164
|
+
spec.original_platform = spec.platform
|
165
|
+
|
166
|
+
Gem::Builder.new(spec).build
|
167
|
+
end
|
168
|
+
|
169
|
+
desc 'Install the sys-proctable library as a gem'
|
170
|
+
task :install => [:create] do
|
171
|
+
gem_name = Dir['*.gem'].first
|
172
|
+
sh "gem install #{gem_name}"
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
task :default => :test
|
@@ -0,0 +1,21 @@
|
|
1
|
+
########################################################################
|
2
|
+
# bench_ps.rb
|
3
|
+
#
|
4
|
+
# Benchmark program to show overall speed and compare the block form
|
5
|
+
# versus the non-block form. You should run this benchmark via the
|
6
|
+
# 'rake bench' Rake task.
|
7
|
+
########################################################################
|
8
|
+
require 'benchmark'
|
9
|
+
require 'sys/proctable'
|
10
|
+
|
11
|
+
MAX = 10
|
12
|
+
|
13
|
+
Benchmark.bm do |bench|
|
14
|
+
bench.report("Block form"){
|
15
|
+
MAX.times{ Sys::ProcTable.ps{} }
|
16
|
+
}
|
17
|
+
|
18
|
+
bench.report("Non-block form"){
|
19
|
+
MAX.times{ Sys::ProcTable.ps }
|
20
|
+
}
|
21
|
+
end
|
data/doc/top.txt
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
= Description
|
2
|
+
A simple 'top' interface for Ruby
|
3
|
+
|
4
|
+
= Prerequisites
|
5
|
+
Requires the "sys/proctable" package (which should be installed along
|
6
|
+
with this package).
|
7
|
+
|
8
|
+
= Synopsis
|
9
|
+
require "sys/top"
|
10
|
+
|
11
|
+
Sys::Top.top(5).each{ |ps|
|
12
|
+
p ps
|
13
|
+
}
|
14
|
+
|
15
|
+
= Constants
|
16
|
+
VERSION
|
17
|
+
Returns the version number of this package as a String.
|
18
|
+
|
19
|
+
= Class Methods
|
20
|
+
Sys::Top.top(number=10, field="pctcpu")
|
21
|
+
Returns an array of ProcTableStruct's. The size of the array (i.e. the
|
22
|
+
number of processes) that it returns is based on +number+, and sorted by
|
23
|
+
+pctcpu+. By default, the size and field values are 10 and "pctcpu",
|
24
|
+
respectively.
|
25
|
+
|
26
|
+
= Notes
|
27
|
+
Not all fields are available on all platforms. Please check your
|
28
|
+
platform specific documentation for which fields are available.
|
29
|
+
|
30
|
+
= Bugs
|
31
|
+
None that I'm aware of. Please log bug reports on the project page at
|
32
|
+
http://www.rubyforge.org/projects/sysutils
|
33
|
+
|
34
|
+
= License
|
35
|
+
Artistic 2.0
|
36
|
+
|
37
|
+
= Copyright
|
38
|
+
(C) 2004-2009 Daniel J. Berger
|
39
|
+
All Rights Reserved.
|
40
|
+
|
41
|
+
= Warranty
|
42
|
+
This package is provided "as is" and without any express or
|
43
|
+
implied warranties, including, without limitation, the implied
|
44
|
+
warranties of merchantability and fitness for a particular purpose.
|
45
|
+
|
46
|
+
= Author
|
47
|
+
Daniel J. Berger
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#######################################################################
|
2
|
+
# example_ps.rb
|
3
|
+
#
|
4
|
+
# Generic test program that demonstrates the use of ProcTable.ps. You
|
5
|
+
# can run this via the 'rake example' task.
|
6
|
+
#
|
7
|
+
# Modify as you see fit
|
8
|
+
#######################################################################
|
9
|
+
require 'sys/proctable'
|
10
|
+
include Sys
|
11
|
+
|
12
|
+
puts "VERSION: " + ProcTable::VERSION
|
13
|
+
sleep 2
|
14
|
+
|
15
|
+
ProcTable.ps{ |s|
|
16
|
+
ProcTable.fields.each{ |field|
|
17
|
+
puts "#{field}: " + s.send(field).to_s
|
18
|
+
}
|
19
|
+
puts '=' * 30
|
20
|
+
}
|
data/ext/bsd/extconf.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
have_type('rb_pid_t', 'ruby.h')
|
4
|
+
|
5
|
+
have_library('kvm')
|
6
|
+
have_func('kvm_openfiles')
|
7
|
+
have_struct_member('struct kinfo_proc', 'kp_proc', 'sys/user.h')
|
8
|
+
have_struct_member('struct kinfo_proc', 'kp_eproc', 'sys/user.h')
|
9
|
+
have_struct_member('struct kinfo_proc', 'u_kproc', 'sys/user.h')
|
10
|
+
have_struct_member('struct eproc', 'e_stats', 'sys/sysctl.h')
|
11
|
+
have_struct_member('struct eproc', 'p_oncpu', 'sys/sysctl.h')
|
12
|
+
have_struct_member('struct eproc', 'p_runtime', 'sys/sysctl.h')
|
13
|
+
|
14
|
+
create_makefile('sys/proctable', 'sys')
|
@@ -0,0 +1,301 @@
|
|
1
|
+
/**********************************************************************
|
2
|
+
* proctable.c
|
3
|
+
*
|
4
|
+
* This is a generic kvm interface used by the various BSD flavors
|
5
|
+
* for the sys-proctable library.
|
6
|
+
**********************************************************************/
|
7
|
+
#include "ruby.h"
|
8
|
+
#include <kvm.h>
|
9
|
+
#include <sys/param.h>
|
10
|
+
#include <sys/stat.h>
|
11
|
+
#include <sys/sysctl.h>
|
12
|
+
#include <sys/types.h>
|
13
|
+
#include <sys/user.h>
|
14
|
+
|
15
|
+
#define SYS_PROCTABLE_VERSION "0.9.1"
|
16
|
+
|
17
|
+
VALUE cProcTableError, sProcStruct;
|
18
|
+
|
19
|
+
const char* fields[] = {
|
20
|
+
"pid", "ppid", "pgid", "ruid",
|
21
|
+
"rgid", "comm", "state", "pctcpu", "oncpu", "ttynum", "ttydev", "wmesg",
|
22
|
+
"time", "priority", "usrpri", "nice", "cmdline", "start",
|
23
|
+
"maxrss", "ixrss", "idrss", "isrss", "minflt", "majflt", "nswap",
|
24
|
+
"inblock", "oublock", "msgsnd", "msgrcv", "nsignals", "nvcsw", "nivcsw",
|
25
|
+
"utime", "stime"
|
26
|
+
};
|
27
|
+
|
28
|
+
/*
|
29
|
+
* call-seq:
|
30
|
+
* ProcTable.ps(pid=nil)
|
31
|
+
* ProcTable.ps(pid=nil){ |ps| ... }
|
32
|
+
*
|
33
|
+
* In block form, yields a ProcTableStruct for each process entry that you
|
34
|
+
* have rights to. This method returns an array of ProcTableStruct's in
|
35
|
+
* non-block form.
|
36
|
+
*
|
37
|
+
* If a +pid+ is provided, then only a single ProcTableStruct is yielded or
|
38
|
+
* returned, or nil if no process information is found for that +pid+.
|
39
|
+
*/
|
40
|
+
static VALUE pt_ps(int argc, VALUE* argv, VALUE klass){
|
41
|
+
kvm_t *kd;
|
42
|
+
char errbuf[_POSIX2_LINE_MAX];
|
43
|
+
char cmdline[_POSIX_ARG_MAX+1];
|
44
|
+
char state[8];
|
45
|
+
char** args = malloc(sizeof(char*));
|
46
|
+
struct kinfo_proc* procs;
|
47
|
+
int count; // Holds total number of processes
|
48
|
+
int i = 0;
|
49
|
+
VALUE v_pid, v_tty_num, v_tty_dev, v_start_time;
|
50
|
+
VALUE v_pstruct = Qnil;
|
51
|
+
VALUE v_array = Qnil;
|
52
|
+
|
53
|
+
rb_scan_args(argc, argv, "01", &v_pid);
|
54
|
+
|
55
|
+
if(!NIL_P(v_pid))
|
56
|
+
Check_Type(v_pid, T_FIXNUM);
|
57
|
+
|
58
|
+
if(!rb_block_given_p())
|
59
|
+
v_array = rb_ary_new();
|
60
|
+
|
61
|
+
// Open the kvm interface, get a descriptor
|
62
|
+
if((kd = kvm_open(NULL, NULL, NULL, 0, "kvm_open")) == NULL)
|
63
|
+
rb_raise(cProcTableError, "kvm_open failed: %s", strerror(errno));
|
64
|
+
|
65
|
+
// Get the list of processes
|
66
|
+
if((procs = kvm_getprocs(kd, KERN_PROC_ALL, 0, &count)) == NULL) {
|
67
|
+
strcpy(errbuf, kvm_geterr(kd));
|
68
|
+
kvm_close(kd);
|
69
|
+
rb_raise(cProcTableError, errbuf);
|
70
|
+
}
|
71
|
+
|
72
|
+
for(i=0; i<count; i++){
|
73
|
+
// Reset some variables
|
74
|
+
v_tty_num = Qnil;
|
75
|
+
v_tty_dev = Qnil;
|
76
|
+
v_start_time = Qnil;
|
77
|
+
|
78
|
+
// If a PID is provided, skip unless the PID matches
|
79
|
+
if(!NIL_P(v_pid)){
|
80
|
+
#ifdef HAVE_ST_KP_PROC
|
81
|
+
if(procs[i].kp_proc.p_pid != NUM2INT(v_pid))
|
82
|
+
continue;
|
83
|
+
#else
|
84
|
+
if(procs[i].ki_pid != NUM2INT(v_pid))
|
85
|
+
continue;
|
86
|
+
#endif
|
87
|
+
}
|
88
|
+
|
89
|
+
// Get the command line arguments for the process
|
90
|
+
cmdline[0] = '\0';
|
91
|
+
args = kvm_getargv(kd, (const struct kinfo_proc *)&procs[i], 0);
|
92
|
+
|
93
|
+
if(args){
|
94
|
+
int j = 0;
|
95
|
+
while (args[j] && strlen(cmdline) <= _POSIX_ARG_MAX) {
|
96
|
+
strcat(cmdline, args[j]);
|
97
|
+
strcat(cmdline, " ");
|
98
|
+
j++;
|
99
|
+
}
|
100
|
+
}
|
101
|
+
|
102
|
+
// Get the start time of the process
|
103
|
+
v_start_time = rb_time_new(
|
104
|
+
#ifdef HAVE_ST_E_STATS
|
105
|
+
procs[i].kp_eproc.e_stats.p_start.tv_sec,
|
106
|
+
procs[i].kp_eproc.e_stats.p_start.tv_usec
|
107
|
+
#else
|
108
|
+
0,0
|
109
|
+
#endif
|
110
|
+
);
|
111
|
+
|
112
|
+
// Get the state of the process
|
113
|
+
#ifdef HAVE_ST_KP_PROC
|
114
|
+
switch(procs[i].kp_proc.p_stat)
|
115
|
+
#else
|
116
|
+
switch(procs[i].ki_stat)
|
117
|
+
#endif
|
118
|
+
{
|
119
|
+
case SIDL:
|
120
|
+
strcpy(state, "idle");
|
121
|
+
break;
|
122
|
+
case SRUN:
|
123
|
+
strcpy(state, "run");
|
124
|
+
break;
|
125
|
+
case SSLEEP:
|
126
|
+
strcpy(state, "sleep");
|
127
|
+
break;
|
128
|
+
case SSTOP:
|
129
|
+
strcpy(state, "stop");
|
130
|
+
break;
|
131
|
+
case SZOMB:
|
132
|
+
strcpy(state, "zombie");
|
133
|
+
break;
|
134
|
+
default:
|
135
|
+
strcpy(state, "unknown");
|
136
|
+
break;
|
137
|
+
}
|
138
|
+
|
139
|
+
// Get ttynum and ttydev. If ttynum is -1, there is no tty
|
140
|
+
#ifdef HAVE_ST_KP_EPROC
|
141
|
+
v_tty_num = INT2FIX(procs[i].kp_eproc.e_tdev),
|
142
|
+
v_tty_dev = rb_str_new2(devname(procs[i].kp_eproc.e_tdev, S_IFCHR));
|
143
|
+
#elif HAVE_ST_U_KPROC
|
144
|
+
v_tty_num = INT2FIX(procs[i].u_kproc.ki_tdev),
|
145
|
+
v_tty_dev = rb_str_new2(devname(procs[i].u_kproc.ki_tdev, S_IFCHR));
|
146
|
+
#else
|
147
|
+
v_tty_num = INT2FIX(procs[i].ki_tdev),
|
148
|
+
v_tty_dev = rb_str_new2(devname(procs[i].ki_tdev, S_IFCHR));
|
149
|
+
#endif
|
150
|
+
|
151
|
+
#ifdef HAVE_ST_KP_PROC
|
152
|
+
v_pstruct = rb_struct_new(
|
153
|
+
sProcStruct,
|
154
|
+
INT2FIX(procs[i].kp_proc.p_pid),
|
155
|
+
INT2FIX(procs[i].kp_eproc.e_ppid),
|
156
|
+
INT2FIX(procs[i].kp_eproc.e_pgid),
|
157
|
+
INT2FIX(procs[i].kp_eproc.e_pcred.p_ruid),
|
158
|
+
INT2FIX(procs[i].kp_eproc.e_pcred.p_rgid),
|
159
|
+
rb_str_new2(procs[i].kp_proc.p_comm),
|
160
|
+
rb_str_new2(state),
|
161
|
+
rb_float_new(procs[i].kp_proc.p_pctcpu),
|
162
|
+
#ifdef HAVE_ST_P_ONCPU
|
163
|
+
INT2FIX(procs[i].kp_proc.p_oncpu),
|
164
|
+
#else
|
165
|
+
Qnil,
|
166
|
+
#endif
|
167
|
+
v_tty_num,
|
168
|
+
v_tty_dev,
|
169
|
+
rb_str_new2(procs[i].kp_eproc.e_wmesg),
|
170
|
+
#ifdef HAVE_ST_P_RUNTIME
|
171
|
+
INT2FIX(procs[i].kp_proc.p_runtime/1000000),
|
172
|
+
#else
|
173
|
+
Qnil,
|
174
|
+
#endif
|
175
|
+
INT2FIX(procs[i].kp_proc.p_priority),
|
176
|
+
INT2FIX(procs[i].kp_proc.p_usrpri),
|
177
|
+
INT2FIX(procs[i].kp_proc.p_nice),
|
178
|
+
rb_str_new2(cmdline),
|
179
|
+
v_start_time,
|
180
|
+
#ifdef HAVE_ST_E_STATS
|
181
|
+
LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_maxrss),
|
182
|
+
LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_ixrss),
|
183
|
+
LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_idrss),
|
184
|
+
LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_isrss),
|
185
|
+
LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_minflt),
|
186
|
+
LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_majflt),
|
187
|
+
LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_nswap),
|
188
|
+
LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_inblock),
|
189
|
+
LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_oublock),
|
190
|
+
LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_msgsnd),
|
191
|
+
LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_msgrcv),
|
192
|
+
LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_nsignals),
|
193
|
+
LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_nvcsw),
|
194
|
+
LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_nivcsw),
|
195
|
+
LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_utime.tv_sec),
|
196
|
+
LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_stime.tv_sec)
|
197
|
+
#else
|
198
|
+
Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil,
|
199
|
+
Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil
|
200
|
+
#endif
|
201
|
+
);
|
202
|
+
#else
|
203
|
+
v_pstruct = rb_struct_new(
|
204
|
+
sProcStruct,
|
205
|
+
INT2FIX(procs[i].ki_pid),
|
206
|
+
INT2FIX(procs[i].ki_ppid),
|
207
|
+
INT2FIX(procs[i].ki_pgid),
|
208
|
+
INT2FIX(procs[i].ki_ruid),
|
209
|
+
INT2FIX(procs[i].ki_rgid),
|
210
|
+
rb_str_new2(procs[i].ki_ocomm),
|
211
|
+
rb_str_new2(state),
|
212
|
+
rb_float_new(procs[i].ki_pctcpu),
|
213
|
+
INT2FIX(procs[i].ki_oncpu),
|
214
|
+
v_tty_num,
|
215
|
+
v_tty_dev,
|
216
|
+
rb_str_new2(procs[i].ki_wmesg),
|
217
|
+
INT2FIX(procs[i].ki_runtime/1000000),
|
218
|
+
INT2FIX(procs[i].ki_pri.pri_level),
|
219
|
+
INT2FIX(procs[i].ki_pri.pri_user),
|
220
|
+
INT2FIX(procs[i].ki_nice),
|
221
|
+
rb_str_new2(cmdline),
|
222
|
+
v_start_time,
|
223
|
+
Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil,
|
224
|
+
Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil
|
225
|
+
);
|
226
|
+
#endif
|
227
|
+
|
228
|
+
OBJ_FREEZE(v_pstruct); // Read-only data
|
229
|
+
|
230
|
+
if(rb_block_given_p())
|
231
|
+
rb_yield(v_pstruct);
|
232
|
+
else
|
233
|
+
rb_ary_push(v_array, v_pstruct);
|
234
|
+
}
|
235
|
+
|
236
|
+
if(kd)
|
237
|
+
kvm_close(kd);
|
238
|
+
|
239
|
+
if(!NIL_P(v_pid))
|
240
|
+
return v_pstruct;
|
241
|
+
|
242
|
+
return v_array; // Nil if block given
|
243
|
+
}
|
244
|
+
|
245
|
+
/*
|
246
|
+
* call-seq:
|
247
|
+
* ProcTable.fields
|
248
|
+
*
|
249
|
+
* Returns an array of fields that each ProcTableStruct will contain. This
|
250
|
+
* may be useful if you want to know in advance what fields are available
|
251
|
+
* without having to perform at least one read of the /proc table.
|
252
|
+
*/
|
253
|
+
static VALUE pt_fields(VALUE klass){
|
254
|
+
VALUE v_array = rb_ary_new();
|
255
|
+
int size = sizeof(fields) / sizeof(fields[0]);
|
256
|
+
int i;
|
257
|
+
|
258
|
+
for(i = 0; i < size; i++)
|
259
|
+
rb_ary_push(v_array, rb_str_new2(fields[i]));
|
260
|
+
|
261
|
+
return v_array;
|
262
|
+
}
|
263
|
+
|
264
|
+
/*
|
265
|
+
* A Ruby interface for gathering process table information.
|
266
|
+
*/
|
267
|
+
void Init_proctable(){
|
268
|
+
VALUE mSys, cProcTable;
|
269
|
+
|
270
|
+
/* The Sys module serves as a namespace only */
|
271
|
+
mSys = rb_define_module("Sys");
|
272
|
+
|
273
|
+
/* The ProcTable class encapsulates process table information */
|
274
|
+
cProcTable = rb_define_class_under(mSys, "ProcTable", rb_cObject);
|
275
|
+
|
276
|
+
/* The error typically raised if any of the ProcTable methods fail */
|
277
|
+
cProcTableError = rb_define_class_under(cProcTable, "Error", rb_eStandardError);
|
278
|
+
|
279
|
+
/* Singleton Methods */
|
280
|
+
|
281
|
+
rb_define_singleton_method(cProcTable, "ps", pt_ps, -1);
|
282
|
+
rb_define_singleton_method(cProcTable, "fields", pt_fields, 0);
|
283
|
+
|
284
|
+
/* There is no constructor */
|
285
|
+
rb_funcall(cProcTable, rb_intern("private_class_method"), 1, ID2SYM(rb_intern("new")));
|
286
|
+
|
287
|
+
/* Constants */
|
288
|
+
|
289
|
+
/* 0.9.1: The version of the sys-proctable library */
|
290
|
+
rb_define_const(cProcTable, "VERSION", rb_str_new2(SYS_PROCTABLE_VERSION));
|
291
|
+
|
292
|
+
/* Structures */
|
293
|
+
|
294
|
+
sProcStruct = rb_struct_define("ProcTableStruct","pid","ppid","pgid","ruid",
|
295
|
+
"rgid","comm","state","pctcpu","oncpu","ttynum","ttydev","wmesg",
|
296
|
+
"time", "priority","usrpri","nice","cmdline","start",
|
297
|
+
"maxrss","ixrss","idrss","isrss","minflt","majflt","nswap",
|
298
|
+
"inblock","oublock","msgsnd","msgrcv","nsignals","nvcsw","nivcsw",
|
299
|
+
"utime","stime", NULL
|
300
|
+
);
|
301
|
+
}
|