Project 1: System Inspector (v 1.0)
Starter repository on GitHub: https://classroom.github.com/a/NL5zCUW1
Our journey through the operating system starts in userland (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:
[magical-unicorn:~/P1-malensek]$ ./inspector System Information ------------------ Hostname: magical-unicorn Kernel Version: 4.20.3-arch1-1-ARCH Uptime: 32 minutes, 35 seconds Hardware Information -------------------- CPU Model: AMD EPYC Processor (with IBPB) Processing Units: 2 Load Average (1/5/15 min): 0.15 0.06 0.01 CPU Usage: [##########----------] 50.3% Memory Usage: [--------------------] 4.6% (0.0 GB / 1.0 GB) Task Information ---------------- Tasks running: 88 Since boot: Interrupts: 44349 Context Switches: 88340 Forks: 421 PID | State | Task Name | User | Tasks ------+--------------+---------------------------+-----------------+------- 1 | sleeping | systemd | root | 1 2 | sleeping | kthreadd | root | 1 3 | idle | rcu_gp | root | 1 4 | idle | rcu_par_gp | root | 1 (the entire list of processes is printed -- truncated for brevity)
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
cd /procin your shell and then run
lsto view the files. You’ll see process IDs and several other virtual files that are updated dynamically with system information. Each line shown above in the process listing corresponds to a numbered directory in
- Check out the man page:
man proc. The manual has a complete description of every file and directory stored under
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:
close()system calls for reading file data
- Tokenizing text files
readdirfunctions for listing directory contents
statfor getting file information
getpwuid()to map user IDs to user names
- Argument parsing with
- Load averages, calculating CPU usage, and Linux tasks
Each portion of the display can be toggled with 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 [-ahlrst] [-p procfs_dir] Options: * -a Display all (equivalent to -lrst, default) * -h Help/usage information * -l Task List * -p procfs_dir Change the expected procfs mount point (default: /proc) * -r Hardware Information * -s System Information * -t Task Information
So the task list, hardware information, system information, and task information can all be turned on/off with the command line options. By default, all of them are displayed.
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
Populating the Output
Here’s some tips to guide your implementation:
- You can use the
chdirsystem call to make supporting the
-poption easier. Just chdir to the specified directory and open files as relative paths.
- Remember to close the files/directories you open! If too many file descriptors are left open, subsequent open calls will fail.
- Truncate strings that are too long to display (applicable to the process and user names). Otherwise, your formatting won’t be correct. See the example
printfformat string below for the column lengths.
- Use the amount of active memory when reporting memory usage.
When calculating uptime, don’t report years, days, or hours if their respective values are 0. If a machine has just booted up, you’ll display
Uptime: 0 minutes, 42 seconds, for example. The fields you need to support are:
CPU usage is calculated by sampling over a period of time, i.e., the CPU was active for 70% of one second. You should record the CPU usage, sleep for one second, 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:
1 - ( (idle2 - idle1) / (total2 - total1) )
If the CPU usage percentage is NaN (not a number), report 0%.
You should format your output as shown in the example above. For the process list, the
printf format string used is:
printf("%5s | %12s | %25s | %15s | %s \n", "PID", "State", "Task Name", "User", "Tasks");
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
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
getline, etc. You are also required to write your own string tokenization functionality with
strcspn – don’t use
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 thread safe) that make it a bad choice. We are writing our own version of
strcspn so that when we need to parse more complicated inputs in later projects we’ll be able to do so.
Failure to follow these guidelines will result in severe deductions or a 0.
Testing Your Code
Check your code against the provided test cases. You should make sure your code runs on your Arch Linux VM. We’ll have interactive grading for projects, where you will demonstrate program functionality and walk through your logic.
Submission: submit via GitHub by checking in your code before the project deadline. You must include a makefile with your project. As part of the testing process, we will check out your code and run
make to build it.
- 20 pts - Passing the test cases.
- 2 pts - Proper cleanup: directory entries, memory, etc.
- 3 pts - Code formatting, organization, and documentation:
- Each function should have a description of its inputs, outputs, and purpose (unless it’s so trivial that no explanation is required).
- Complicated code segments should include comments to describe functionality.
- No dead, leftover, or unnecessary code.
- The project must include a makefile.
- You must include a README.md file that describes your program, how it works, how to build it, and any other relevant details. You’ll be happy you did this later if/when your revisit the codebase.
- 1 pts - Make a live-updating view of the processes, similar to how
Nprocesses should print, where
Nis the number of lines visible on the terminal.
- 1 pts - Build a running process tree, similar to how
- Added more details for CPU usage, uptime (2/18)
- Initial project specification posted (2/4)