• This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.

Solved How to get CPU(s) load as in "top", in C

Nicola Mingotti

Active Member

Thanks: 96
Messages: 204

#1
Hi,

I am porting a C program from Linux To FreeBSD (wmmon FYI) and I would like
to know how i can get cpu(s) load as I can read them from "top" command.

I found in other posts here sysctl dev.cpu but that me gives always 100%.
I would need to get what "top" calls { "user", "system", "interrupt" and "idle" } ...
or least two cathegories "idle" and "not-idle".

What I see from "sysctl.dev.cpu"
Code:
dev.cpu.0.cx_method: C1/hlt
dev.cpu.0.cx_usage_counters: 2062148
dev.cpu.0.cx_usage: 100.00% last 5097us
dev.cpu.0.cx_lowest: C2
dev.cpu.0.cx_supported: C1/1/0
dev.cpu.0.%domain: 0
dev.cpu.0.%parent: acpi0
dev.cpu.0.%pnpinfo: _HID=none _UID=0
dev.cpu.0.%location: handle=\_SB_.CP00 _PXM=0
dev.cpu.0.%driver: cpu
dev.cpu.0.%desc: ACPI CPU
dev.cpu.%parent:
What "top" shows
Code:
...
CPU:  3.5% user,  0.0% nice,  2.4% system,  1.2% interrupt, 92.9% idle
...
I thought about reading "top" code, but if I understood well, "top" is part
of the FreeBSD-system, so I would need to download all the system source to read it and
my disk space is very very scarce. I only have 1GB available now. I guess I can't do that.

Bye
Nicola
 

tobik@

Daemon
Developer

Thanks: 1,327
Messages: 1,908

#2
I thought about reading "top" code, but if I understood well, "top" is part
of the FreeBSD-system, so I would need to download all the system source to read it and
my disk space is very very scarce. I only have 1GB available now. I guess I can't do that.
You can checkout top sources directly (< 1 MB):

svnlite co https://svn.freebsd.org/base/head/contrib/top
svnlite co https://svn.freebsd.org/base/head/usr.bin/top usr.bin-top
 

Nicola Mingotti

Active Member

Thanks: 96
Messages: 204

#4
Hi, guys ! Thank you again for adding a line to your post @tobik
I was going mad to find that "machine.c" ! :)

Bye the way, is there a way to easily link another person name in a post ?
sorry for the small off topic.
 

tobik@

Daemon
Developer

Thanks: 1,327
Messages: 1,908

#5
Hi, guys ! Thank you again for adding a line to your post @tobik
I was going mad to find that "machine.c" ! :)

Bye the way, is there a way to easily link another person name in a post ?
sorry for the small off topic.
You did it the right way, however whatever comes after the @ must be an exact match for a username, so @tobik@ for tobik@ or @Nicola Mingotti for Nicola Mingotti
 

Nicola Mingotti

Active Member

Thanks: 96
Messages: 204

#6
Ok guys, I red the code and I was able to solve it.
The key point is file machine.c, at function get_system_info
The raw values can be seen with sysctl kern.cp_times.

I write here a Ruby script that gets the same values "top" gives.
Porting it to C should be almost trivial.
I put no effort in styling the Ruby, I think it is very understandable
as it is now.

Why Ruby? because it is almost practical as Perl and almost readable as Python.
I bit of propaganda for a scripting language I really like;)

Here goes the code for people how may need it in future.
I mark the Thread as Solved, Thank you all for your assistance.

==========================
ATTENTION, the code is not correctly displayed! I don't know
how to fix this, use the file I attached if you want the true
working code
==========================

Code:
while true do
  st1 = `sysctl kern.cp_times`
  st1.chomp!
  vals1 = st1.split(/ /); vals1.shift
  sleep 1
  st2 = `sysctl kern.cp_times`
  st2.chomp!
  vals2 = st2.split(/ /); vals2.shift
  diffs = [-1,-1,-1,-1,-1]
  (0..4).each do |i|
    diffs = vals2.to_f - vals1.to_f
  end
  tot = diffs.sum
  diffsPerc = [-1,-1,-1,-1,-1]
  (0..4).each do |i|
    diffsPerc = (diffs / tot) * 100.0
  end
  userv = "%.1f" % diffsPerc[0]; nicev = "%.1f" % diffsPerc[1]
  systemv = "%.1f" % diffsPerc[2]; interv = "%.1f" % diffsPerc[3]
  idlev = "%.1f" % diffsPerc[4]
  puts "CPU: #{userv}% user, #{nicev}% nice, #{systemv}% system, " +
       "#{interv}% interrupt, #{idlev}% idle"
end
 

Attachments

Nicola Mingotti

Active Member

Thanks: 96
Messages: 204

#7
ATTENTION, code in the above block is not correctly represented !!!
I uploaded a file for the correct version as it should be displayed.

Is this a BUG in forum code widget ?
 

tobik@

Daemon
Developer

Thanks: 1,327
Messages: 1,908

#8
[i] is a BBCode for writing text in italic, so you might have to wrap the code in [noparse] tags.

This will hopefully show up correctly:
Code:
[noparse]
while true do 
  st1 = `sysctl kern.cp_times`
  st1.chomp!
  vals1 = st1.split(/ /); vals1.shift
  sleep 1
  st2 = `sysctl kern.cp_times`
  st2.chomp!
  vals2 = st2.split(/ /); vals2.shift 
  diffs = [-1,-1,-1,-1,-1]
  (0..4).each do |i| 
    diffs[i] = vals2[i].to_f - vals1[i].to_f
  end
  tot = diffs.sum
  diffsPerc = [-1,-1,-1,-1,-1]
  (0..4).each do |i|
    diffsPerc[i] = (diffs[i] / tot) * 100.0
  end
  userv = "%.1f" % diffsPerc[0]; nicev = "%.1f" % diffsPerc[1]
  systemv = "%.1f" % diffsPerc[2]; interv = "%.1f" % diffsPerc[3]
  idlev = "%.1f" % diffsPerc[4]
  puts "CPU: #{userv}% user, #{nicev}% nice, #{systemv}% system, " +
       "#{interv}% interrupt, #{idlev}% idle"
end 
[/noparse]
I'm not sure if this should be considered a bug. It's generally nice to be able to format and highlight things in [code] blocks.
 

Nicola Mingotti

Active Member

Thanks: 96
Messages: 204

#10
I learn more thing here in one day than I could in one week alone.
This is wonderful place !

Thank you tobik@ for the {noparse} tag.
[USER]Eric A. Borisch[/USER], I will put your link in my notes, it can be very useful.

IMHO this behaviour for CODE block is very dangerous, it breaks
the POLA principle {I learnt this thing here;} , I guess all people take for granted that a code
block is verbtim and they can liberally copy/paste, which is not true.

I opened a thread in "general" about this "bug", I will follow up
the discussion in that place that seems more appropriate.

Bye
Nicola
 
Top