linux_stat 2.0.1 → 2.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/exe/linuxstat.rb CHANGED
@@ -150,9 +150,9 @@ execute.sort.each do |c|
150
150
  disp_meth = "#{meth}"
151
151
  disp_meth.concat(arg ? "(#{param})" : "(#{param})")
152
152
 
153
- time = Time.now
153
+ time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
154
154
  ret = arg ? e.send(meth, arg) : e.send(meth)
155
- time2 = Time.now
155
+ time2 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
156
156
  time = time2.-(time).*(1_000_000).round(3)
157
157
 
158
158
  v = ret.inspect
data/ext/procfs/procfs.c CHANGED
@@ -38,5 +38,6 @@ int Init_procfs() {
38
38
 
39
39
  // stat
40
40
  rb_define_module_function(_procfs, "ps_state", ps_state, 1) ;
41
+ rb_define_module_function(_procfs, "ps_times", ps_times, 1) ;
41
42
  rb_define_module_function(_procfs, "ps_stat", ps_stat, 1) ;
42
43
  }
data/ext/procfs/stat.h CHANGED
@@ -1,6 +1,9 @@
1
1
  VALUE ps_state(VALUE obj, VALUE pid) {
2
+ int _pid = FIX2INT(pid) ;
3
+ if (_pid < 0) return rb_str_new_cstr("") ;
4
+
2
5
  char _path[22] ;
3
- sprintf(_path, "/proc/%lu/stat", FIX2UINT(pid)) ;
6
+ sprintf(_path, "/proc/%d/stat", _pid) ;
4
7
 
5
8
  FILE *f = fopen(_path, "r") ;
6
9
  if (!f) return rb_str_new_cstr("") ;
@@ -14,9 +17,33 @@ VALUE ps_state(VALUE obj, VALUE pid) {
14
17
  return rb_str_new_cstr(_s) ;
15
18
  }
16
19
 
20
+ VALUE ps_times(VALUE obj, VALUE pid) {
21
+ int _pid = FIX2INT(pid) ;
22
+ if (_pid < 0) return Qnil ;
23
+
24
+ char _path[22] ;
25
+ sprintf(_path, "/proc/%d/stat", _pid) ;
26
+
27
+ FILE *f = fopen(_path, "r") ;
28
+ if (!f) return Qnil ;
29
+
30
+ unsigned long utime, stime ;
31
+
32
+ char status = fscanf(f, "%*llu (%*[^)]%*[)] %*c %*d %*d %*d %*d %*d %*u %*lu %*lu %*lu %*lu %lu %lu", &utime, &stime) ;
33
+ fclose(f) ;
34
+
35
+ if (status != 2) return Qnil ;
36
+ double total_time = (utime + stime) / (float)sysconf(_SC_CLK_TCK);
37
+
38
+ return DBL2NUM(total_time) ;
39
+ }
40
+
17
41
  VALUE ps_stat(VALUE obj, VALUE pid) {
42
+ int _pid = FIX2INT(pid) ;
43
+ if (_pid < 0) return rb_str_new_cstr("") ;
44
+
18
45
  char _path[22] ;
19
- sprintf(_path, "/proc/%lu/stat", FIX2UINT(pid)) ;
46
+ sprintf(_path, "/proc/%d/stat", _pid) ;
20
47
 
21
48
  FILE *f = fopen(_path, "r") ;
22
49
 
data/ext/procfs/statm.h CHANGED
@@ -1,13 +1,15 @@
1
1
  #define PAGESIZE sysconf(_SC_PAGESIZE)
2
2
 
3
3
  VALUE statm(VALUE obj, VALUE pid) {
4
- char _path[22] ;
5
- sprintf(_path, "/proc/%lu/statm", FIX2UINT(pid)) ;
4
+ VALUE hash = rb_hash_new() ;
6
5
 
7
- FILE *f = fopen(_path, "r") ;
6
+ int _pid = FIX2INT(pid) ;
7
+ if (_pid < 0) return hash ;
8
8
 
9
- VALUE hash = rb_hash_new() ;
9
+ char _path[22] ;
10
+ sprintf(_path, "/proc/%d/statm", _pid) ;
10
11
 
12
+ FILE *f = fopen(_path, "r") ;
11
13
  if (!f) return hash ;
12
14
 
13
15
  unsigned int _virtual, resident, shared ;
@@ -33,13 +35,15 @@ VALUE statm(VALUE obj, VALUE pid) {
33
35
  }
34
36
 
35
37
  VALUE statm_virtual(VALUE obj, VALUE pid) {
38
+ int _pid = FIX2INT(pid) ;
39
+ if (_pid < 0) return Qnil ;
40
+
36
41
  char _path[22] ;
37
- sprintf(_path, "/proc/%lu/statm", FIX2UINT(pid)) ;
42
+ sprintf(_path, "/proc/%d/statm", _pid) ;
38
43
 
39
44
  FILE *f = fopen(_path, "r") ;
40
- VALUE hash = rb_hash_new() ;
45
+ if (!f) return Qnil ;
41
46
 
42
- if (!f) return hash ;
43
47
  unsigned int _virtual ;
44
48
  char status = fscanf(f, "%u", &_virtual) ;
45
49
  fclose(f) ;
@@ -49,13 +53,15 @@ VALUE statm_virtual(VALUE obj, VALUE pid) {
49
53
  }
50
54
 
51
55
  VALUE statm_resident(VALUE obj, VALUE pid) {
56
+ int _pid = FIX2INT(pid) ;
57
+ if (_pid < 0) return Qnil ;
58
+
52
59
  char _path[22] ;
53
- sprintf(_path, "/proc/%lu/statm", FIX2UINT(pid)) ;
60
+ sprintf(_path, "/proc/%d/statm", _pid) ;
54
61
 
55
62
  FILE *f = fopen(_path, "r") ;
56
- VALUE hash = rb_hash_new() ;
63
+ if (!f) return Qnil ;
57
64
 
58
- if (!f) return hash ;
59
65
  unsigned int resident ;
60
66
  char status = fscanf(f, "%*u %u", &resident) ;
61
67
  fclose(f) ;
@@ -65,13 +71,15 @@ VALUE statm_resident(VALUE obj, VALUE pid) {
65
71
  }
66
72
 
67
73
  VALUE statm_shared(VALUE obj, VALUE pid) {
74
+ int _pid = FIX2INT(pid) ;
75
+ if (_pid < 0) return Qnil ;
76
+
68
77
  char _path[22] ;
69
- sprintf(_path, "/proc/%lu/statm", FIX2UINT(pid)) ;
78
+ sprintf(_path, "/proc/%d/statm", _pid) ;
70
79
 
71
80
  FILE *f = fopen(_path, "r") ;
72
- VALUE hash = rb_hash_new() ;
81
+ if (!f) return Qnil ;
73
82
 
74
- if (!f) return hash ;
75
83
  unsigned int shared ;
76
84
  char status = fscanf(f, "%*u %*u %u", &shared) ;
77
85
  fclose(f) ;
@@ -81,11 +89,13 @@ VALUE statm_shared(VALUE obj, VALUE pid) {
81
89
  }
82
90
 
83
91
  VALUE statm_memory(VALUE obj, VALUE pid) {
92
+ int _pid = FIX2INT(pid) ;
93
+ if (_pid < 0) return Qnil ;
94
+
84
95
  char _path[22] ;
85
- sprintf(_path, "/proc/%lu/statm", FIX2UINT(pid)) ;
96
+ sprintf(_path, "/proc/%d/statm", _pid) ;
86
97
 
87
98
  FILE *f = fopen(_path, "r") ;
88
-
89
99
  if (!f) return Qnil ;
90
100
 
91
101
  unsigned int resident, shared ;
@@ -105,11 +105,19 @@ module LinuxStat
105
105
  #
106
106
  # If the battery is not present or the information is not available, it will return nil.
107
107
  def charge
108
- @@charge_now_file ||= File.join(PATH, 'charge_now')
109
- @@charge_full_file ||= File.join(PATH, 'charge_full')
108
+ @@charge_now_file ||= if File.readable?(File.join(PATH, 'charge_now'))
109
+ File.join(PATH, 'charge_now').freeze
110
+ elsif File.readable?(File.join(PATH, 'energy_now'))
111
+ File.join(PATH, 'energy_now').freeze
112
+ end
113
+
114
+ @@charge_full_file ||= if File.readable?(File.join(PATH, 'charge_full'))
115
+ File.join(PATH, 'charge_full').freeze
116
+ elsif File.readable?(File.join(PATH, 'energy_full'))
117
+ File.join(PATH, 'energy_full').freeze
118
+ end
110
119
 
111
- @@charge_now_readable ||= File.readable?(@@charge_now_file) && File.readable?(@@charge_full_file)
112
- return nil unless @@charge_now_readable
120
+ return nil unless @@charge_now_file && @@charge_full_file
113
121
 
114
122
  charge_now = IO.read(@@charge_now_file).to_i
115
123
  charge_full = IO.read(@@charge_full_file).to_i
@@ -178,7 +186,14 @@ module LinuxStat
178
186
  # For example, a sample output can be like this (taken on a test system):
179
187
  #
180
188
  # 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}}
189
+ # => {:AC=>{:type=>"Mains", :online=>1},
190
+ # :BAT0=>{:model=>"DELL CYMGM77", :manufacturer=>"Samsung SDI",
191
+ # :type=>"Battery", :status=>"Full", :capacity=>100, :voltage_min_design=>11.4,
192
+ # :charge_full_design=>3.684, :charge_full_design_wh=>42.0,
193
+ # :voltage_now=>12.558, :charge_now=>2.087, :charge_now_wh=>26.21,
194
+ # :charge_full_wh=>23.79, :charge_percentage=>100.0},
195
+ # :hidpp_battery_0=>{:model=>"Wireless Keyboard", :manufacturer=>"Logitech",
196
+ # :type=>"Battery", :status=>"Discharging", :online=>1}}
182
197
  #
183
198
  # If you need info about lots of batteries, use this method.
184
199
  # If the informations are not available, it will return empty Hash for each devices.
@@ -208,7 +223,16 @@ module LinuxStat
208
223
 
209
224
  # charge now
210
225
  cn_f = File.join(x, 'charge_now'.freeze).freeze
211
- charge_now = File.readable?(cn_f) ? IO.read(cn_f).to_i.fdiv(1_000_000) : nil
226
+ charge_now = if File.readable?(cn_f)
227
+ IO.read(cn_f).to_i.fdiv(1_000_000)
228
+ else
229
+ en_f = File.join(x, 'energy_now'.freeze)
230
+ if File.readable?(en_f)
231
+ IO.read(en_f) .to_i.fdiv(1_000_000)
232
+ else
233
+ nil
234
+ end
235
+ end
212
236
 
213
237
  # voltage min design
214
238
  vmd_f = File.join(x, 'voltage_min_design'.freeze).freeze
@@ -220,7 +244,16 @@ module LinuxStat
220
244
 
221
245
  # charge full
222
246
  cf_f = File.join(x, 'charge_full'.freeze).freeze
223
- charge_full = File.readable?(cf_f) ? IO.read(cf_f).to_i.fdiv(1_000_000) : nil
247
+ charge_full = if File.readable?(cf_f)
248
+ IO.read(cf_f).to_i.fdiv(1_000_000)
249
+ else
250
+ ef_f = File.join(x, 'energy_full'.freeze)
251
+ if File.readable?(ef_f)
252
+ IO.read(ef_f).to_i.fdiv(1_000_000)
253
+ else
254
+ nil
255
+ end
256
+ end
224
257
 
225
258
  # status
226
259
  s_f = File.join(x, 'status'.freeze).freeze
data/lib/linux_stat/os.rb CHANGED
@@ -7,7 +7,11 @@ module LinuxStat
7
7
  # Reads /etc/os-release and returns a Hash. For example:
8
8
  # LinuxStat::OS.os_release
9
9
  #
10
- # => {:NAME=>"Arch Linux", :PRETTY_NAME=>"Arch Linux", :ID=>"arch", :BUILD_ID=>"rolling", :ANSI_COLOR=>"38;2;23;147;209", :HOME_URL=>"https://www.archlinux.org/", :DOCUMENTATION_URL=>"https://wiki.archlinux.org/", :SUPPORT_URL=>"https://bbs.archlinux.org/", :BUG_REPORT_URL=>"https://bugs.archlinux.org/", :LOGO=>"archlinux"}
10
+ # => {:NAME=>"Arch Linux", :PRETTY_NAME=>"Arch Linux", :ID=>"arch", :BUILD_ID=>"rolling",
11
+ # :ANSI_COLOR=>"38;2;23;147;209", :HOME_URL=>"https://www.archlinux.org/",
12
+ # :DOCUMENTATION_URL=>"https://wiki.archlinux.org/",
13
+ # :SUPPORT_URL=>"https://bbs.archlinux.org/", :BUG_REPORT_URL=>"https://bugs.archlinux.org/",
14
+ # :LOGO=>"archlinux"}
11
15
  #
12
16
  # If the info isn't available, it will return an empty Hash.
13
17
  #
@@ -127,7 +131,7 @@ module LinuxStat
127
131
  #
128
132
  # The return type is strictly Integer and doesn't fail.
129
133
  def bits
130
- @@bits ||= if RbConfig::CONFIG['host_cpu'].end_with?('64') || RUBY_PLATFORM.end_with?('64') || machine.end_with?('64')
134
+ @@bits ||= if machine.end_with?('64') || RbConfig::CONFIG['host_cpu'].end_with?('64') || RUBY_PLATFORM.end_with?('64')
131
135
  64
132
136
  else
133
137
  32
@@ -138,7 +142,7 @@ module LinuxStat
138
142
  # Reads /proc/uptime and returns the system uptime:
139
143
  # LinuxStat::OS.uptime
140
144
  #
141
- # => {:hour=>10, :minute=>34, :second=>12.59}
145
+ # => {:hour=>16, :minute=>10, :second=>11, :jiffy=>20}
142
146
  #
143
147
  # Using uptime is 10x slower than using uptime_i
144
148
  #
@@ -151,12 +155,14 @@ module LinuxStat
151
155
 
152
156
  h = uptime_i / 3600
153
157
  m = uptime_i % 3600 / 60
154
- s = _uptime.%(3600).%(60).round(2)
158
+ s = uptime_i.%(60)
159
+ j = _uptime.-(uptime_i) * 100
155
160
 
156
161
  {
157
162
  hour: h,
158
163
  minute: m,
159
- second: s
164
+ second: s,
165
+ jiffy: j.to_i
160
166
  }
161
167
  end
162
168
 
@@ -283,7 +283,7 @@ module LinuxStat
283
283
  uptime = LS::ProcFS.uptime_f
284
284
  return {} unless uptime && !stat.empty?
285
285
 
286
- utime, stime, starttime = *stat.values_at(11, 12, 19).map(&:to_f)
286
+ utime, stime, starttime = *stat.values_at(10, 11, 18).map(&:to_f)
287
287
  uptime *= ticks
288
288
 
289
289
  total_time = utime + stime
@@ -295,14 +295,14 @@ module LinuxStat
295
295
  uptime = LS::ProcFS.uptime_f
296
296
  return {} unless uptime && !stat.empty?
297
297
 
298
- utime2, stime2, starttime2 = *stat.values_at(11, 12, 19).map(&:to_f)
298
+ utime2, stime2, starttime2 = *stat.values_at(10, 11, 18).map(&:to_f)
299
299
  uptime *= ticks
300
300
 
301
301
  total_time2 = utime2 + stime2
302
302
  idle2 = uptime - starttime2 - total_time2
303
303
 
304
304
  totald = idle2.+(total_time2).-(idle1 + total_time)
305
- cpu_u = totald.-(idle2 - idle1).fdiv(totald).abs.*(100)./(cpu_count)
305
+ cpu_u = totald.-(idle2 - idle1).fdiv(totald).abs.*(100)./(LinuxStat::CPU.count)
306
306
 
307
307
  {
308
308
  cpu_usage: cpu_u > 100 ? 100.0 : cpu_u.round(2),
@@ -338,32 +338,10 @@ module LinuxStat
338
338
  #
339
339
  # This method is more efficient than running LinuxStat::ProcessInfo.cpu_stat()
340
340
  def cpu_usage(pid: $$, sleep: ticks_to_ms_t5)
341
- ticks = get_ticks
342
- stat = LinuxStat::ProcFS.ps_stat(pid)
343
- uptime = LS::ProcFS.uptime_f
344
- return nil unless uptime && !stat.empty?
345
-
346
- utime, stime, starttime = *stat.values_at(10, 11, 18).map(&:to_f)
347
- uptime *= ticks
348
-
349
- total_time = utime + stime
350
- idle1 = uptime - starttime - total_time
351
-
352
- sleep(sleep)
353
-
354
- stat = LinuxStat::ProcFS.ps_stat(pid)
355
- uptime = LS::ProcFS.uptime_f
356
- return nil unless uptime && !stat.empty?
357
-
358
- utime2, stime2, starttime2 = *stat.values_at(10, 11, 18).map(&:to_f)
359
- uptime *= ticks
360
-
361
- total_time2 = utime2 + stime2
362
- idle2 = uptime - starttime2 - total_time2
341
+ u = cpu_usage_thread(pid, sleep)
342
+ return nil unless u
363
343
 
364
- totald = idle2.+(total_time2).-(idle1 + total_time)
365
-
366
- u = totald.-(idle2 - idle1).fdiv(totald).abs.*(100)./(cpu_count)
344
+ u /= LinuxStat::CPU.count
367
345
  u > 100 ? 100.0 : u.round(2)
368
346
  end
369
347
 
@@ -390,34 +368,10 @@ module LinuxStat
390
368
  #
391
369
  # But if the info isn't available, it will return nil.
392
370
  def thread_usage(pid: $$, sleep: ticks_to_ms_t5)
393
- ticks = get_ticks
394
- stat = LinuxStat::ProcFS.ps_stat(pid)
395
- uptime = LS::ProcFS.uptime_f
396
- return nil unless uptime && !stat.empty?
397
-
398
- utime, stime, starttime = *stat.values_at(10, 11, 18).map(&:to_f)
399
- uptime *= ticks
400
-
401
- total_time = utime + stime
402
- idle1 = uptime - starttime - total_time
371
+ u = cpu_usage_thread(pid, sleep)
372
+ return nil unless u
403
373
 
404
- sleep(sleep)
405
-
406
- stat = LinuxStat::ProcFS.ps_stat(pid)
407
- uptime = LS::ProcFS.uptime_f
408
- return nil unless uptime && !stat.empty?
409
-
410
- utime2, stime2, starttime2 = *stat.values_at(10, 11, 18).map(&:to_f)
411
- uptime *= ticks
412
-
413
- total_time2 = utime2 + stime2
414
- idle2 = uptime - starttime2 - total_time2
415
-
416
- totald = idle2.+(total_time2).-(idle1 + total_time)
417
-
418
- u = totald.-(idle2 - idle1).fdiv(totald).abs.*(100)
419
-
420
- cpu_count_t100 = cpu_count * 100
374
+ cpu_count_t100 = LinuxStat::CPU.count * 100
421
375
  u > cpu_count_t100 ? cpu_count_t100 : u.round(2)
422
376
  end
423
377
 
@@ -655,6 +609,47 @@ module LinuxStat
655
609
  LinuxStat::Nproc.count_cpu_for_pid(pid)
656
610
  end
657
611
 
612
+ ##
613
+ # = def cpu_times_i(pid = $$)
614
+ #
615
+ # Shows the CPU time used by the process.
616
+ #
617
+ # The return value is a Float.
618
+ # But if the info isn't available, it will return nil.
619
+ def cpu_time(pid = $$)
620
+ LinuxStat::ProcFS.ps_times(pid)
621
+ end
622
+
623
+ ##
624
+ # = def cpu_times(pid = $$)
625
+ #
626
+ # Shows the CPU time used by the process.
627
+ #
628
+ # The return value is a Hash formatted like this:
629
+ # LS::ProcessInfo.cpu_times($$)
630
+ #
631
+ # => {:hour=>0, :minute=>39, :second=>12, :jiffy=>0.42}
632
+ #
633
+ # But if the info isn't available, it will return an empty Hash..
634
+ def cpu_times(pid = $$)
635
+ v = LinuxStat::ProcFS.ps_times(pid)
636
+ return {} unless v
637
+
638
+ v_i = v.to_i
639
+
640
+ hour = v_i / 3600
641
+ min = v_i % 3600 / 60
642
+ sec = v_i % 60
643
+ jiffy = v.-(v_i) * 100
644
+
645
+ {
646
+ hour: hour,
647
+ minute: min,
648
+ second: sec,
649
+ jiffy: jiffy.to_i
650
+ }
651
+ end
652
+
658
653
  alias count_cpu nproc
659
654
 
660
655
  private
@@ -674,8 +669,33 @@ module LinuxStat
674
669
  @@pagesize ||= LinuxStat::Sysconf.pagesize.to_i
675
670
  end
676
671
 
677
- def cpu_count
678
- @@nprocessors_conf ||= LinuxStat::CPU.count
672
+ def cpu_usage_thread(pid, delay)
673
+ ticks = get_ticks
674
+ stat = LinuxStat::ProcFS.ps_stat(pid)
675
+ uptime = LS::ProcFS.uptime_f
676
+ return nil unless uptime && !stat.empty?
677
+
678
+ utime, stime, starttime = *stat.values_at(10, 11, 18).map(&:to_f)
679
+ uptime *= ticks
680
+
681
+ total_time = utime + stime
682
+ idle1 = uptime - starttime - total_time
683
+
684
+ sleep(delay)
685
+
686
+ stat = LinuxStat::ProcFS.ps_stat(pid)
687
+ uptime = LS::ProcFS.uptime_f
688
+ return nil unless uptime && !stat.empty?
689
+
690
+ utime2, stime2, starttime2 = *stat.values_at(10, 11, 18).map(&:to_f)
691
+ uptime *= ticks
692
+
693
+ total_time2 = utime2 + stime2
694
+ idle2 = uptime - starttime2 - total_time2
695
+
696
+ totald = idle2.+(total_time2).-(idle1 + total_time)
697
+
698
+ totald.-(idle2 - idle1).fdiv(totald).abs.*(100)
679
699
  end
680
700
  end
681
701
  end