Project 1: System Inspector (v 1.0)

Starter repository on GitHub: https://classroom.github.com/a/C9U2qWAU

Our journey through the operating system starts in user space, outside the kernel. In this project, we’ll implement a Unix utility that inspects the system it runs on and creates a summarized report for the user. If you’ve ever used the top command from a shell, our program will be somewhat similar. To give you an idea of how your program will work, here’s a quick example:

Hostname: magical-unicorn | Kernel Version: 5.15.4 | CPUs: 2
Uptime: 16 days, 11:25:42

Load Average (1/5/15 min): 0.09 0.14 0.09
CPU Usage:    [######--------------] 30.0%
Memory Usage: [#####---------------] 29.3% (421.7 MiB / 1.4 GiB)

Tasks: 101 total
2 running, 0 waiting, 98 sleeping, 1 stopped, 0 zombie

      PID |                 Task Name |        State |            User
----------+---------------------------+--------------+-----------------
     9783 |                      sshd |      running |            root
    11642 |                        sl |      stopped |       mmalensek
    12701 |                 inspector |      running |       mmalensek

To get this information, you will use the proc, the process information pseudo-filesystem. While there are other ways to get the information displayed above, you are restricted to using proc in this assignment. There are two great resources for finding out what information is available in proc:

For a quick example, try running cat /proc/uptime. You’ll see the number of seconds the system has been running printed to the terminal.

In this assignment, you will get experience working with:

The program supports a few command line options. We’ll let the program do the talking by printing usage information (-h option):

[magical-unicorn:~/P1-malensek]$ ./inspector -h
Usage: ./inspector [-ho] [-i interval] [-p procfs_dir]

Options:
    * -h              Display help/usage information
    * -i interval     Set the update interval (default: 1000ms)
    * -p procfs_dir   Set the expected procfs mount point (default: /proc)
    * -o              Operate in one-shot mode (no curses or live updates)

Pay particular attention to the -p flag. This allows us to change the directory where proc is mounted (/proc by default). We will use this option to test your code with our own pre-populated copy of proc.

Populating the Output

Your main responsibility in this project is implementing a variety of procfs-related functions (prefixed pfs_*) to retrieve the required information. The UI for the program was written using the ncurses library – assuming your pfs_* functions work properly, you shouldn’t need to worry about modifying the UI (although you are welcome to do so). In ‘one-shot’ mode, the simple UI is disabled and printed directly to the terminal instead.

Here’s some tips to guide your implementation:

Hostname, Kernel Version, CPUs, Load Average

These should be straightforward to locate and extract the data for with minimal post-processing.

Uptime

Format uptime as D day[s], HH:MM:SS. If the machine has been running for 1 day, do not print the ’s' in ‘days.’ If the machine has been running for less than 1 day, only print the hours, minutes, and seconds of uptime.

Overall CPU Usage

CPU usage is calculated by sampling over a period of time, i.e., the CPU was active for 70% of one second. You will record the CPU usage, sleep for one second (this is handled by the UI code), and then get a second reading to determine the usage percentage. The CPU metrics in /proc/stat will add up to 100% because idle time is included. You’ll need to track idle time separately, so the calculation will look something like:

(usage2 - usage1) / (total2 - total1)

Where usage1 and total1 are from the first sample and usage2 and total2 are from the second sample. You’re effectively calculating the change in these two samples to get a usage percentage.

If the CPU usage percentage is NaN (not a number), or you encounter errors performing the calculation, report 0%. Since this calculation requires two samples, your function should take the previous sample as one of its arguments.

Process States

You should support all of the process states listed in the proc man pages. Additionally, for our purposes, we will consider ‘idle’ processes equivalent to ‘sleeping.’ To build the “running, waiting, sleeping, …” output, the specific state flags you’ll be interested in are R, S, I, D, Z, T, and t.

Idle and sleeping (I and S) processes are not shown in the program output.

UIDs

You’ll notice that proc doesn’t contain information about the username associated with running processes, but it does provide their ID numbers (UIDs). To map UIDs to usernames, you will need to parse the contents of /etc/passwd. While there are functions that will do this for you, such as getpwuid, you are required to build your own lookup functionality. (Note: getpwuid can seemingly leak memory in certain situations, so we’re avoiding it here).

Implementation Restrictions

Restrictions: you may use any standard C library functionality. External libraries are not allowed unless permission is granted in advance. Your code must compile and run on your VM set up with Arch Linux as described in class – failure to do so will receive a grade of 0.

While there are several ways to retrieve the system information displayed by your project, you must retrieve the data from /proc only.

One of the major components of this assignment is reading and parsing text files. To read the files, you are required to use the read system call instead of the fancier C library functions like fgets, getline, scanf, etc. You also shouldn’t use getpwuid or strtok, and processing the text files using regular expressions is not allowed.

Rationale: we’re using read here to get familiar with how I/O works at a lower level. You will need to be able to understand read for subsequent assignments. As for strtok, it has several pitfalls (including not being reentrant or thread safe) that make it a bad choice. You can either use strsep or the next_token implementation provided in class.

Failure to follow these guidelines will result in severe deductions (at least 10 points) or a 0.

Grading

Check your code against the provided test cases. You should make sure your code runs on your Arch Linux VM.

Submission: submit via GitHub by checking in your code before the project deadline.

Your grade is based on:

Changelog