linux_stat 1.4.0 → 2.1.1

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.
@@ -0,0 +1,11 @@
1
+ require 'mkmf'
2
+
3
+ unless have_const('linux') || RbConfig::CONFIG['arch'].to_s[/linux/]
4
+ abort('Platform is not linux')
5
+ end
6
+
7
+ unless have_header('sys/sysinfo.h') && have_header('ruby.h')
8
+ abort('Missing header')
9
+ end
10
+
11
+ create_makefile 'linux_stat/sysinfo'
@@ -0,0 +1,177 @@
1
+ #include <sys/sysinfo.h>
2
+ #include "ruby.h"
3
+
4
+ #if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER)
5
+ #pragma GCC optimize ("O3")
6
+ #pragma GCC diagnostic warning "-Wall"
7
+ #elif defined(__clang__)
8
+ #pragma clang optimize on
9
+ #pragma clang diagnostic warning "-Wall"
10
+ #elif defined(__INTEL_COMPILER)
11
+ #pragma intel optimization_level 3
12
+ #endif
13
+
14
+ static struct sysinfo info ;
15
+
16
+ VALUE totalram(VALUE obj) {
17
+ char status = sysinfo(&info) ;
18
+ if (status < 0) return Qnil ;
19
+
20
+ VALUE _rb_v = ULL2NUM((unsigned long long) info.totalram) ;
21
+ VALUE _rb_mem_unit = ULL2NUM((unsigned long long) info.mem_unit) ;
22
+ return rb_funcallv_public(_rb_v, rb_intern("*"), 1, &_rb_mem_unit) ;
23
+ }
24
+
25
+ VALUE freeram(VALUE obj) {
26
+ char status = sysinfo(&info) ;
27
+ if (status < 0) return Qnil ;
28
+
29
+ VALUE _rb_v = ULL2NUM((unsigned long long) info.freeram) ;
30
+ VALUE _rb_mem_unit = ULL2NUM((unsigned long long) info.mem_unit) ;
31
+ return rb_funcallv_public(_rb_v, rb_intern("*"), 1, &_rb_mem_unit) ;
32
+ }
33
+
34
+ VALUE sharedram(VALUE obj) {
35
+ char status = sysinfo(&info) ;
36
+ if (status < 0) return Qnil ;
37
+
38
+ VALUE _rb_v = ULL2NUM((unsigned long long) info.sharedram) ;
39
+ VALUE _rb_mem_unit = ULL2NUM((unsigned long long) info.mem_unit) ;
40
+ return rb_funcallv_public(_rb_v, rb_intern("*"), 1, &_rb_mem_unit) ;
41
+ }
42
+
43
+ VALUE bufferram(VALUE obj) {
44
+ char status = sysinfo(&info) ;
45
+ if (status < 0) return Qnil ;
46
+
47
+ VALUE _rb_v = ULL2NUM((unsigned long long) info.bufferram) ;
48
+ VALUE _rb_mem_unit = ULL2NUM((unsigned long long) info.mem_unit) ;
49
+ return rb_funcallv_public(_rb_v, rb_intern("*"), 1, &_rb_mem_unit) ;
50
+ }
51
+
52
+ VALUE totalswap(VALUE obj) {
53
+ static struct sysinfo info ;
54
+ char status = sysinfo(&info) ;
55
+ if (status < 0) return Qnil ;
56
+
57
+ VALUE _rb_v = ULL2NUM((unsigned long long) info.totalswap) ;
58
+ VALUE _rb_mem_unit = ULL2NUM((unsigned long long) info.mem_unit) ;
59
+ return rb_funcallv_public(_rb_v, rb_intern("*"), 1, &_rb_mem_unit) ;
60
+ }
61
+
62
+ VALUE freeswap(VALUE obj) {
63
+ char status = sysinfo(&info) ;
64
+ if (status < 0) return Qnil ;
65
+
66
+ VALUE _rb_v = ULL2NUM((unsigned long long) info.freeswap) ;
67
+ VALUE _rb_mem_unit = ULL2NUM((unsigned long long) info.mem_unit) ;
68
+ return rb_funcallv_public(_rb_v, rb_intern("*"), 1, &_rb_mem_unit) ;
69
+ }
70
+
71
+ VALUE totalhigh(VALUE obj) {
72
+ char status = sysinfo(&info) ;
73
+ if (status < 0) return Qnil ;
74
+
75
+ VALUE _rb_v = ULL2NUM((unsigned long long) info.totalhigh) ;
76
+ VALUE _rb_mem_unit = ULL2NUM((unsigned long long) info.mem_unit) ;
77
+ return rb_funcallv_public(_rb_v, rb_intern("*"), 1, &_rb_mem_unit) ;
78
+ }
79
+
80
+ VALUE freehigh(VALUE obj) {
81
+ char status = sysinfo(&info) ;
82
+ if (status < 0) return Qnil ;
83
+
84
+ VALUE _rb_v = ULL2NUM((unsigned long long) info.freehigh) ;
85
+ VALUE _rb_mem_unit = ULL2NUM((unsigned long long) info.mem_unit) ;
86
+ return rb_funcallv_public(_rb_v, rb_intern("*"), 1, &_rb_mem_unit) ;
87
+ }
88
+
89
+ VALUE uptime(VALUE obj) {
90
+ char status = sysinfo(&info) ;
91
+ if (status < 0) return Qnil ;
92
+
93
+ unsigned long long v = info.uptime ;
94
+ return ULL2NUM((unsigned long long) v) ;
95
+ }
96
+
97
+ VALUE loads(VALUE obj) {
98
+ char status = sysinfo(&info) ;
99
+ if(status < 0) return rb_ary_new() ;
100
+
101
+ long double load = 1.f / (1 << SI_LOAD_SHIFT) ;
102
+
103
+ float l_1 = info.loads[0] * load ;
104
+ float l_5 = info.loads[1] * load ;
105
+ float l_15 = info.loads[2] * load ;
106
+
107
+ return rb_ary_new_from_args(3,
108
+ rb_float_new(l_1),
109
+ rb_float_new(l_5),
110
+ rb_float_new(l_15)
111
+ ) ;
112
+ }
113
+
114
+ // Some people may need this function, just keep it to not make unnecessary calls
115
+ VALUE sysinfoStat(VALUE obj) {
116
+ char status = sysinfo(&info) ;
117
+ VALUE hash = rb_hash_new() ;
118
+ if (status < 0) return hash ;
119
+
120
+ unsigned long long mem_unit = info.mem_unit ;
121
+ VALUE _rb_mem_unit = ULL2NUM(mem_unit) ;
122
+
123
+ unsigned long long _totalram = info.totalram ;
124
+ unsigned long long _freeram = info.freeram ;
125
+ unsigned long long _sharedram = info.sharedram ;
126
+ unsigned long long _bufferram = info.bufferram ;
127
+ unsigned long long _totalswap = info.totalswap ;
128
+ unsigned long long _freeswap = info.freeswap ;
129
+ unsigned long long _totalhigh = info.totalhigh ;
130
+ unsigned long long _freehigh = info.freehigh ;
131
+ unsigned long long _uptime = info.uptime ;
132
+
133
+ long double load = 1.f / (1 << SI_LOAD_SHIFT) ;
134
+
135
+ float l_1 = info.loads[0] * load ;
136
+ float l_5 = info.loads[1] * load ;
137
+ float l_15 = info.loads[2] * load ;
138
+
139
+ VALUE loads = rb_ary_new_from_args(3,
140
+ rb_float_new(l_1),
141
+ rb_float_new(l_5),
142
+ rb_float_new(l_15)
143
+ ) ;
144
+
145
+ VALUE mul = rb_intern("*") ;
146
+
147
+ rb_hash_aset(hash, ID2SYM(rb_intern("totalram")), rb_funcallv_public(ULL2NUM(_totalram), mul, 1, &_rb_mem_unit)) ;
148
+ rb_hash_aset(hash, ID2SYM(rb_intern("freeram")), rb_funcallv_public(ULL2NUM(_freeram), mul, 1, &_rb_mem_unit)) ;
149
+ rb_hash_aset(hash, ID2SYM(rb_intern("sharedram")), rb_funcallv_public(ULL2NUM(_sharedram), mul, 1, &_rb_mem_unit)) ;
150
+ rb_hash_aset(hash, ID2SYM(rb_intern("bufferram")), rb_funcallv_public(ULL2NUM(_bufferram), mul, 1, &_rb_mem_unit)) ;
151
+ rb_hash_aset(hash, ID2SYM(rb_intern("totalswap")), rb_funcallv_public(ULL2NUM(_totalswap), mul, 1, &_rb_mem_unit)) ;
152
+ rb_hash_aset(hash, ID2SYM(rb_intern("freeswap")), rb_funcallv_public(ULL2NUM(_freeswap), mul, 1, &_rb_mem_unit)) ;
153
+ rb_hash_aset(hash, ID2SYM(rb_intern("totalhigh")), rb_funcallv_public(ULL2NUM(_totalhigh), mul, 1, &_rb_mem_unit)) ;
154
+ rb_hash_aset(hash, ID2SYM(rb_intern("freehigh")), rb_funcallv_public(ULL2NUM(_freehigh), mul, 1, &_rb_mem_unit)) ;
155
+ rb_hash_aset(hash, ID2SYM(rb_intern("uptime")), rb_funcallv_public(ULL2NUM(_uptime), mul, 1, &_rb_mem_unit)) ;
156
+
157
+ rb_hash_aset(hash, ID2SYM(rb_intern("loads")), loads) ;
158
+
159
+ return hash ;
160
+ }
161
+
162
+ void Init_sysinfo() {
163
+ VALUE _linux_stat = rb_define_module("LinuxStat") ;
164
+ VALUE _sysinfo = rb_define_module_under(_linux_stat, "Sysinfo") ;
165
+
166
+ rb_define_module_function(_sysinfo, "totalram", totalram, 0) ;
167
+ rb_define_module_function(_sysinfo, "freeram", freeram, 0) ;
168
+ rb_define_module_function(_sysinfo, "sharedram", sharedram, 0) ;
169
+ rb_define_module_function(_sysinfo, "bufferram", bufferram, 0) ;
170
+ rb_define_module_function(_sysinfo, "totalswap", totalswap, 0) ;
171
+ rb_define_module_function(_sysinfo, "freeswap", freeswap, 0) ;
172
+ rb_define_module_function(_sysinfo, "totalhigh", totalhigh, 0) ;
173
+ rb_define_module_function(_sysinfo, "freehigh", freehigh, 0) ;
174
+ rb_define_module_function(_sysinfo, "uptime", uptime, 0) ;
175
+ rb_define_module_function(_sysinfo, "loads", loads, 0) ;
176
+ rb_define_module_function(_sysinfo, "stat", sysinfoStat, 0) ;
177
+ }
@@ -17,7 +17,7 @@ static char *sysname = "", *nodename = "" ;
17
17
  static char *release = "", *version = "", *machine = "" ;
18
18
 
19
19
  void init_buf() {
20
- short status = uname(&buf) ;
20
+ char status = uname(&buf) ;
21
21
 
22
22
  if (status > -1) {
23
23
  sysname = buf.sysname ;
data/lib/linux_stat.rb CHANGED
@@ -23,20 +23,26 @@ require "linux_stat/version"
23
23
  # But might be required by other module functions in "Dependent Modules" section
24
24
  require "linux_stat/battery"
25
25
  require "linux_stat/bios"
26
- require "linux_stat/memory"
27
26
  require "linux_stat/net"
28
27
  require "linux_stat/pci"
29
- require "linux_stat/process"
30
- require "linux_stat/swap"
31
28
  require "linux_stat/thermal"
32
29
  require "linux_stat/usb"
33
30
 
34
31
  # Dependent Modules
35
32
  # Modules that can have reverse dependency
36
33
 
34
+ # LinuxStat::ProcFS dependent modules
35
+ require "linux_stat/procfs"
36
+ require "linux_stat/process"
37
+
38
+ # LinuxStat::CPU.sysinfo dependent modules
39
+ require "linux_stat/sysinfo"
40
+ require "linux_stat/swap"
41
+ require "linux_stat/memory"
42
+
37
43
  # LinuxStat::CPU.nproc dependent modules
38
- require "linux_stat/cpu"
39
44
  require "linux_stat/nproc"
45
+ require "linux_stat/cpu"
40
46
 
41
47
  # LinuxStat::Uname dependent modules
42
48
  require 'linux_stat/utsname'
@@ -178,7 +178,14 @@ module LinuxStat
178
178
  # For example, a sample output can be like this (taken on a test system):
179
179
  #
180
180
  # LinuxStat::Battery.devices_stat
181
- # => {:AC=>{:type=>"Mains", :online=>1}, :BAT0=>{:model=>"DELL CYMGM77", :manufacturer=>"Samsung SDI", :type=>"Battery", :status=>"Full", :capacity=>100, :voltage_min_design=>11.4, :charge_full_design=>3.684, :charge_full_design_wh=>42.0, :voltage_now=>12.558, :charge_now=>2.087, :charge_now_wh=>26.21, :charge_full_wh=>23.79, :charge_percentage=>100.0}, :hidpp_battery_0=>{:model=>"Wireless Keyboard", :manufacturer=>"Logitech", :type=>"Battery", :status=>"Discharging", :online=>1}}
181
+ # => {:AC=>{:type=>"Mains", :online=>1},
182
+ # :BAT0=>{:model=>"DELL CYMGM77", :manufacturer=>"Samsung SDI",
183
+ # :type=>"Battery", :status=>"Full", :capacity=>100, :voltage_min_design=>11.4,
184
+ # :charge_full_design=>3.684, :charge_full_design_wh=>42.0,
185
+ # :voltage_now=>12.558, :charge_now=>2.087, :charge_now_wh=>26.21,
186
+ # :charge_full_wh=>23.79, :charge_percentage=>100.0},
187
+ # :hidpp_battery_0=>{:model=>"Wireless Keyboard", :manufacturer=>"Logitech",
188
+ # :type=>"Battery", :status=>"Discharging", :online=>1}}
182
189
  #
183
190
  # If you need info about lots of batteries, use this method.
184
191
  # If the informations are not available, it will return empty Hash for each devices.
@@ -35,13 +35,23 @@ module LinuxStat
35
35
  end
36
36
 
37
37
  ##
38
- # Returns the total memory details reported by /proc/meminfo.
38
+ # Returns the total memory reported by LS::Sysinfo.totalram()
39
39
  # The value is in Kilobyte.
40
40
  #
41
41
  # It retuns an Integer but if the info is not available, it will return nil.
42
42
  def total
43
- return nil unless meminfo?
44
- IO.foreach('/proc/meminfo'.freeze).first.split[1].to_i
43
+ v = LinuxStat::Sysinfo.totalram
44
+ v ? v.fdiv(1024).to_i : nil
45
+ end
46
+
47
+ ##
48
+ # Returns the free memory reported by LS::Sysinfo.freeram()
49
+ # The value is in Kilobyte.
50
+ #
51
+ # It retuns an Integer but if the info is not available, it will return nil.
52
+ def free
53
+ v = LinuxStat::Sysinfo.freeram
54
+ v ? v.fdiv(1024).to_i : nil
45
55
  end
46
56
 
47
57
  ##
@@ -30,7 +30,7 @@ module LinuxStat
30
30
  data = IO.readlines(DEV).drop(2)
31
31
  indices = find_index_of_bytes
32
32
  data.reject! { |x| x.strip.start_with?('lo:') }
33
- r, t = data.map { |x| x.split.values_at(*indices).map(&:to_i) }.transpose.map(&:sum)
33
+ r, t = data.map { |x| x.split.values_at(*indices).map(&:to_i) }.transpose.map { |x| x.reduce(:+) }
34
34
 
35
35
  {
36
36
  received: r,
@@ -48,7 +48,7 @@ module LinuxStat
48
48
  data = IO.readlines(DEV).drop(2)
49
49
  index = find_index_of_bytes[0]
50
50
  data.reject! { |x| x.strip.start_with?('lo:') }
51
- data.map { |x| x.split[index].to_i }.sum
51
+ data.map { |x| x.split[index].to_i }.reduce(:+)
52
52
  end
53
53
 
54
54
  ##
@@ -61,7 +61,7 @@ module LinuxStat
61
61
  data = IO.readlines(DEV).drop(2)
62
62
  index = find_index_of_bytes[-1]
63
63
  data.reject! { |x| x.strip.start_with?('lo:') }
64
- data.map { |x| x.split[index].to_i }.sum
64
+ data.map { |x| x.split[index].to_i }.reduce(:+)
65
65
  end
66
66
 
67
67
  ##
@@ -89,13 +89,13 @@ module LinuxStat
89
89
  data = IO.readlines(DEV).drop(2)
90
90
  indices = find_index_of_bytes
91
91
  data.reject! { |x| x.strip.start_with?('lo:'.freeze) }
92
- r, t = data.map { |x| x.split.values_at(*indices).map(&:to_i) }.transpose.map(&:sum)
92
+ r, t = data.map { |x| x.split.values_at(*indices).map(&:to_i) }.transpose.map { |x| x.reduce(:+) }
93
93
 
94
94
  sleep(interval)
95
95
 
96
96
  data2 = IO.readlines(DEV).drop(2)
97
97
  data2.reject! { |x| x.strip.start_with?('lo:'.freeze) }
98
- r2, t2 = data2.map { |x| x.split.values_at(*indices).map(&:to_i) }.transpose.map(&:sum)
98
+ r2, t2 = data2.map { |x| x.split.values_at(*indices).map(&:to_i) }.transpose.map { |x| x.reduce(:+) }
99
99
 
100
100
  # Measure the difference
101
101
  dr, dt = r2.-(r).fdiv(interval), t2.-(t).fdiv(interval)
data/lib/linux_stat/os.rb CHANGED
@@ -140,22 +140,73 @@ module LinuxStat
140
140
  #
141
141
  # => {:hour=>10, :minute=>34, :second=>12.59}
142
142
  #
143
+ # Using uptime is 10x slower than using uptime_i
144
+ #
143
145
  # If the stat isn't available, an empty hash is returned.
144
146
  def uptime
145
- return {} unless uptime_readable?
147
+ _uptime = LinuxStat::ProcFS.uptime_f
148
+ return {} unless _uptime
146
149
 
147
- uptime = IO.read('/proc/uptime'.freeze).to_f
148
- uptime_i = uptime.to_i
150
+ uptime_i = _uptime.to_i
149
151
 
150
152
  h = uptime_i / 3600
151
153
  m = uptime_i % 3600 / 60
152
- s = uptime.%(3600).%(60).round(2)
154
+ s = _uptime.%(60).round(2)
153
155
 
154
156
  {
155
157
  hour: h,
156
158
  minute: m,
157
159
  second: s
158
- }.freeze
160
+ }
161
+ end
162
+
163
+ ##
164
+ # Returns Float uptime of the system reported by /proc/uptime
165
+ # LinuxStat::OS.uptime_f
166
+ #
167
+ # => 28956.34
168
+ #
169
+ # The value is generally rounded to 2 decimal places.
170
+ #
171
+ # Using uptime_f is 10x slower than using uptime_i
172
+ #
173
+ # If the stat isn't available, nil is returned.
174
+ def uptime_f
175
+ LinuxStat::ProcFS.uptime_f
176
+ end
177
+
178
+ ##
179
+ # Returns uptime of the system reported by LinuxStat::Sysinfo.uptime()
180
+ # LinuxStat::OS.uptime_i
181
+ #
182
+ # => 28956
183
+ #
184
+ # If the stat isn't available, nil is returned.
185
+ def uptime_i
186
+ LinuxStat::Sysinfo.uptime
187
+ end
188
+
189
+ ##
190
+ # The first three fields in this file are load average
191
+ # figures giving the number of jobs in the run queue (state R)
192
+ # or waiting for disk I/O (state D) averaged over 1, 5,
193
+ # and 15 minutes. They are the same as the load average
194
+ # numbers given by uptime(1) and other programs.
195
+ # https://man7.org/linux/man-pages/man5/procfs.5.html
196
+ #
197
+ # The return type is an Hash containing the values
198
+ # that maps to 1, 5, and 15.
199
+ # This method calls LinuxStat::Sysinfo.loads() directly.
200
+ #
201
+ # However, if the info isn't available, it will return nil as values.
202
+ def loadavg
203
+ loads = LinuxStat::Sysinfo.loads
204
+
205
+ {
206
+ 1 => loads[0],
207
+ 5 => loads[1],
208
+ 15 => loads[2]
209
+ }
159
210
  end
160
211
 
161
212
  alias distrib_version version
@@ -180,10 +231,6 @@ module LinuxStat
180
231
  h.merge!( key.to_sym => value )
181
232
  }
182
233
  end
183
-
184
- def uptime_readable?
185
- @@uptime_readable ||= File.readable?('/proc/uptime')
186
- end
187
234
  end
188
235
  end
189
236
  end
@@ -86,7 +86,7 @@ module LinuxStat
86
86
 
87
87
  begin
88
88
  h.merge!(x =>
89
- case IO.read("/proc/#{x}/stat").split(/(\(.*\))/)[-1][/\s.+?/].strip
89
+ case LinuxStat::ProcFS.ps_state(x)
90
90
  when ?S.freeze then :sleeping
91
91
  when ?I.freeze then :idle
92
92
  when ?Z.freeze then :zombie
@@ -110,11 +110,7 @@ module LinuxStat
110
110
  # The return type is an Array of Integers.
111
111
  def sleeping
112
112
  list.select { |x|
113
- begin
114
- IO.read("/proc/#{x}/stat").split(/(\(.*\))/)[-1][/\s.+?/].strip == ?S.freeze
115
- rescue StandardError
116
- false
117
- end
113
+ LinuxStat::ProcFS.ps_state(x) == ?S.freeze
118
114
  }
119
115
  end
120
116
 
@@ -123,11 +119,7 @@ module LinuxStat
123
119
  # The return type is an Array of Integers.
124
120
  def idle
125
121
  list.select { |x|
126
- begin
127
- IO.read("/proc/#{x}/stat").split(/(\(.*\))/)[-1][/\s.+?/].strip == ?I.freeze
128
- rescue StandardError
129
- false
130
- end
122
+ LinuxStat::ProcFS.ps_state(x) == ?I.freeze
131
123
  }
132
124
  end
133
125
 
@@ -136,11 +128,7 @@ module LinuxStat
136
128
  # The return type is an Array of Integers.
137
129
  def zombie
138
130
  list.select { |x|
139
- begin
140
- IO.read("/proc/#{x}/stat").split(/(\(.*\))/)[-1][/\s.+?/].strip == ?Z.freeze
141
- rescue StandardError
142
- false
143
- end
131
+ LinuxStat::ProcFS.ps_state(x) == ?Z.freeze
144
132
  }
145
133
  end
146
134
 
@@ -149,11 +137,7 @@ module LinuxStat
149
137
  # The return type is an Array of Integers.
150
138
  def running
151
139
  list.select { |x|
152
- begin
153
- IO.read("/proc/#{x}/stat").split(/(\(.*\))/)[-1][/\s.+?/].strip == ?R.freeze
154
- rescue StandardError
155
- false
156
- end
140
+ LinuxStat::ProcFS.ps_state(x) == ?R.freeze
157
141
  }
158
142
  end
159
143
 
@@ -162,14 +146,20 @@ module LinuxStat
162
146
  # The return type is an Array of Integers.
163
147
  def stopped
164
148
  list.select { |x|
165
- begin
166
- v = IO.read("/proc/#{x}/stat").split(/(\(.*\))/)[-1][/\s.+?/].strip
167
- v == ?T.freeze || v == ?t.freeze
168
- rescue StandardError
169
- false
170
- end
149
+ v = LinuxStat::ProcFS.ps_state(x)
150
+ v == ?T.freeze || v == ?t.freeze
171
151
  }
172
152
  end
153
+
154
+ ##
155
+ # Returns the last_pid of the system.
156
+ # It directly calls LS::ProcFS.last_pid
157
+ #
158
+ # The return value is Integer, but if the status
159
+ # isn't available, it will return nil
160
+ def last_pid
161
+ LinuxStat::ProcFS.last_pid
162
+ end
173
163
  end
174
164
  end
175
165
  end