Reading Linux System Info With C++

Ever wondered where utilities like top, jnettop, free and mpstat get their information on CPU usage, network throughput, free RAM etc. from? Well, the majority of it is hidden within the /proc filesystem, most of the rest can be found in /sys and the last few scraps have to be gleaned from elsewhere.

Some of the information held within /proc can also be obtained more directly with the use of a few C libraries. /proc has its own man page which is worth a read but here follows a summary of the files held within it and /sys that are useful for basic system monitoring:

Note: Where a ‘?’ appears in a filename, you must substitute a suitable alphabetic or numeric value for your system in its place.

CPU Utilisation (%)

  • Command: mpstat 1 1
  • File in proc: /proc/stat

For the output of mpstat, add all % columns except “idle” to get the the overall processor usage. By default mpstat reports overall processor usage since power-on, so to get a snapshot of processor usage over the last second, mpstat 1 1 is the command to run.

The values in /proc/stat for CPU utilisation are in 1/100ths of a second since power-on and are presented in a different order to the output of mpstat. See the /proc/stat section here for more information. To get a value for current processor usage, a delta of two readings will have to be made and divided by the time interval between them.

  • Command: uptime
  • File in proc: /proc/loadavg
  • C library: <sys/sysinfo.h>

The uptime command dispays the system uptime and the system load averages taken over time periods of 1, 5 and 15 minutes. In the sysinfo.h library, the struct sysinfo also holds this information.

CPU Temperature

  • Command: sensors
  • File in sys: /sys/bus/platform/devices/coretemp.?/temp?_input

This is a statistic that may not be stored in /proc or /sys and obtaining it may instead rely on the user installing a utility like sensors (lm-sensors) to query, on demand, a hardware specific I2C device on the motherboard. sensors may also provide you with other useful information like GPU temperature and fan speeds that cannot be found in /proc or /sys.

However, if you do have the correct file in proc, the file temp?_input stores the current temperature in 1/1000ths of a degree Celsius. The associated files temp?_label, temp?_max, temp?_crit and temp?_crit_alarm store the CPU/core name and fixed temperature limits. They should all correlate with the output of sensors.

Hard Disk Temperature

  • Command: smartctl -l scttempsts /dev/sda
  • Command: sudo /usr/sbin/hddtemp /dev/sd[abcde]

Out of the two commands, hddtemp produces a much neater output and the square-bracketed section of the command shows how it is easy to fetch temperature data for multiple drives with a single command (something that smartctl cannot do). Adding the -n flag to the hddtemp command produces a more easily parsable output with just a single Celsius value per line.

Hard Disk I/O Statistics (read/write kB/s)

  • Command: iostat
  • File in proc: /proc/diskstats
  • File in sys: /sys/block/?d?/stat

To recreate the numbers that iostat provides for kB read/written per second requires a bit more effort than recreating the other statistics.

The data within /proc is concentrated in a single file, whereas the disk I/O statistics in /sys are spread out in a one-disk-per-file arrangement.

To start with, we need the “sectors read/written” data from one of the aforementioned files taken at two different time intervals as the values in the files are cumulative since power-on. The delta of these two is divided by the interval and then multiplied by a conversion factor. i.e:

(sectors_read_latest_value – sectors_read_last_value) / interval_between_measurements) * conversion_factor

The “sectors read/written” values are from the 6th/10th column of /proc/diskstats or the 3rd/7th colum of /sys/block/?d?/stat. For a final value in kB/s, the conversion factor is 2. For a final value in MB/s, the conversion factor is 2048. The, at first glance, odd, conversion factors stem from the fact that the units of “sectors_read” are blocks of 512 Bytes. Hence 2 * 512 = 1 kB.

For the total amount of data read since power-on, the calculation is sectors_read * conversion_factor.

Hard Disk Size & Free Space

  • Command: df
  • File in sys: /sys/block/?d?/size (drive/partition size in sectors)
  • File in sys: /sys/block/?d?/queue/logical_block_size
  • C library: <sys/statvfs>

Using the /sys files, drive size in bytes is found with the calculation is drive_size_in_sectors * hw_sector_size.

Using the statvfs library, the free space in bytes can be calculated from multiplying the members f_bsize and f_bfree (or f_bavail) of the statvfs struct, while total capacity in bytes can be calculated by multiplying f_blocks and f_frsize.

RAM Utilisation

  • Command: free
  • File in proc: /proc/meminfo
  • C library: <sys/sysinfo.h>
  • C library: <proc/sysinfo.h> (NB: need to link to procps)

In the output from free, the corresponding numbers in /proc/meminfo are

  • total = MemTotal
  • used = MemTotal – MemFree
  • free = MemFree
  • -/+ buffers/cache used = MemTotal – MemFree – Buffers – Cached
  • -/+ buffers/cache free = MemFree + Buffers + Cached

It is the “-/+ buffers/cache” numbers that are more useful.

The library sys/sysinfo provides values for total. free. buffer and shared RAM

Network Statistics

  • Command: netstat -i
  • Command: netstat -ie
  • File in proc: /proc/net/dev

The number of bytes sent/received given in /proc/net/dev are cumulative since boot, so as with the disk throughput, to get measurements in kB/s, the delta of two readings from the file must be divided by the time interval between them.

Time Information

  • Command: uptime
  • Command: date
  • File in proc: /proc/uptime
  • File in proc: /proc/stat
  • C library: <sys/sysinfo.h>
  • C library: <time>
  • C library: <chrono>

in /proc/uptime, the first number in the file is the number of seconds since power-on, the second is the number of seconds spent idle. In the library <sys/sysinfo.h>, the uptime member of the struct sysinfo also gives the number of seconds since power-on.

In /proc/stat, the field btime gives the time at which the system booted, in seconds since the Unix epoch.

The date command displays the current calendar date and local time. However, obtaining calendar dates and times is better done with the <ctime> library.

Sed – match something, then change something else

Here’s a useful feature of sed, the linux stream editor, that I didn’t know about before.

My problem was that within a file, I wanted to only operate on lines that contained a certain expression – but leaving that expression intact and instead changing another expression on that line.

The standard sed command for replacing one expression with another is

sed 's/foo/bar/'

which replaces ‘foo’ with ‘bar’ on every line where ‘foo’ is found. But what if you only want to carry out that replacement on lines that contain the word ‘gnu’? The solution is this…

sed '/gnu/s/foo/bar/'

Regular Expressions for Renaming get_iplayer Downloads

Here are a few useful commands for trimming excess information from the end of files downloaded by get_iplayer.

The commands make use of 3 standard utilities that should be included on any linux distribution. They are find, rename and sed.

You will need to have some understanding of regular expressions to work out how the files are renamed.

Find is used first to provide a coarse list of candidate files to work on. I’m merely using it to recursively list all files in a directory but you can easily fine-tune it with the -name option to filter by filename or file extension. If you don’t want to recurse through directories then you can either skip using find (just using rename) or add -maxdepth 1 as the first argument to find.

Find then passes each matching file it finds to rename which renames the file according to the sed expression it takes as an argument.

To make this a bit safer for anyone reading it, I’ve included the -n flag in the rename command. This modifies the behaviour of rename to not rename anything! Instead it prints out what it would have renamed had the -n “no action” flag not been present. This way, you get to preview all changes before unleashing what may well be a very large and irreversible batch renaming operation.

If you’re at all worried

  • Preview each batch operation with the -n flag for rename
  • Create a backup of any files in the path passed to find
  • Don’t put the backup where find can find it!

Remove iPlayer PIDs from the Filename

from…

The_Killing_Series_3_-_Episode_1_b01p2lyc_default.mp4
The_Killing_Series_3_-_Episode_2_b01p96ft_default.mp4
The_Killing_Series_3_-_Episode_3_b01p2lyf_default.mp4
The_Killing_Series_3_-_Episode_4_b01phjf8_default.mp4

to…

The_Killing_Series_3_-_Episode_1.mp4
The_Killing_Series_3_-_Episode_2.mp4
The_Killing_Series_3_-_Episode_3.mp4
The_Killing_Series_3_-_Episode_4.mp4
find /mnt/media -type f -execdir rename -n 's/_[0-9A-Za-z]{8}_default//' {} \;

Add Leading Zeroes to Episode Numbers

from…

Episode_10.mp4
Episode_1.mp4
Episode_2,mp4
...
Episode_9.mp4

to..

Episode_01.mp4
Episode_02.mp4
...
Episode_09.mp4
Episode_10.mp4
find /mnt/media/ -type f -execdir rename -n 's/Episode_([0-9]){1}([._]){1}/Episode_0$1$2/' {} \;

Remove Spaces From Filenames

Finally, another useful operation (to use on torrent downloads, for example, as iPlayer downloads do not have any) is to remove all spaces from filenames, replacing them with underscores. It affects only the filename, leaving any directories with spaces in the path to the file unchanged. Note the use of of ‘g’ at the end of the sed expression (e.g. ‘s/foo/bar/g’) to replace all occurrences of the pattern, not just the first it finds.

find /mnt/media -type f -execdir rename -n 's/ /_/g' {} \;

Reduced Prices for Memory LCD Breakout Boards

In line with the reduction in Memory LCD prices since I started making my breakout boards, I have reduced the prices of the various Memory LCD Breakout Boards that I am selling. The new prices are:

  • 96 x 96 pixel, 1.35″, PNLC Sharp Memory LCD Breakout Board (5V ONLY)
  • Was £36.50, now £26.50
  • 96 x 96 pixel, 1.35″, PNLC Sharp Memory LCD Breakout Board (3V3 & 5V CAPABLE)
  • Was £36.50, now £32.50
  • 128 x 128 pixel, 1.28″, HR-TFT Sharp Memory LCD Breakout Board
  • Was £36.50, now £32.50
  • 400 x 240 pixel, 2.70″, HR-TFT Sharp Memory LCD Breakout Board
  • Was £56.50, now £48.50

I will likely not be ordering any more 96 x 96 pixel displays so when the last few I’ve currently got in stock are sold, that’s it – no more! My stock levels will be kept updated on the shop page.

I will however continue producing the 128 x 128 pixel and 400 x 240 pixel displays.