# Teaching an absolute beginners class Operating Systems with Rust

In our Bachelor curriculum the course Operating Systems and Computer Networks (5 CP) is designated to be taken in the second semester. Currently it uses C, and while I'm personally very fond of C, it does usually overwhelm the students to learn C enough in order to be able to complete the practical exercises.

However, the focus of the course is not to learn a language but rather the concepts and applying them in small exercises, while getting a "feel" for operating systems or low-level development.

# Issues with C and Rust

• Reading the documentation / man-pages: They're often written for much more experienced people.
• Self-teaching C: It's difficult to find resources both understandable and 'to the point' and 'correct'. Most C only resources, often top hits on Google (e.g. geeks4geeks), are simply wrong code.
• Dealing with undefined behavior.
• Dealing with complex and difficult-to-understand error messages by the compiler.
• Compilation of the program.

A few of these issues could be addressed with Rust:

• The documentation is excellent.
• Online-Tutorials don't need to be perfect as with C, since the compiler is pedantic enough.
• There's no/less undefined behavior.
• The toolchain is easy to use.

Other languages and their issues:

• Python is a popular choice, however I had bad experiences with students being unable to verify their code correctly since it's never compiled and the missing type system can be daunting sometimes as well. Also it often creates a bit too much abstraction in order to be able to look 'into' things.
• Go was used in some advanced courses here for networked programming or parallel programming. It has nice tooling as well but targets a different kind of abstraction as well.
• C++ is simply too complex, while improves some areas of C above, it does so without really removing the pitfalls of C.
• Java has similar issues as Go and Python here.

# Rust Low-Level Abstraction Library

However Rust has many abstractions that actually stop us from being able to really 'go down' the stack and look 'into' what's happening (at least, without understanding the details of Rust which isn't the goal). For example for the students to fiddle around with syscalls they are supposed to write a small cat(1) program using open,close,read,write(3) etc. There's of course the libc crate but using that basically requires knowledge of C and Rust to really deal with things. I thus drafted a small library which I currently host here with really thin abstractions around those syscalls that make dealing with them from Rust quite nicer. 1

The code logic is now quite similar, but hopefully the easier tooling helps the students:

ssize_t n = read(src, buffer, sizeof(buffer));
if (n < 0) { return 1; }
if (n == 0) { return 0; }



Becomes:

let read = match read(src, &mut buffer, BUFSIZ) {
0 => return 0,
n if n < 0 => return 1,
n => n as size_t,
};


And similarly

while (remaining > 0) {
ssize_t written = write(dest, &buffer[read - remaining],
remaining);
if (written < 0) { return 1; }

remaining -= written;
}


is now:

let mut remaining = read;
while remaining > 0 {
let written = match write(dest, &mut buffer[read - remaining..], remaining) {
n if n < 0 => return 1,
n => n as size_t,
};
remaining -= written;
}


I also think it's far less confusing for students to have "return values" to be separate from program "exit codes". However I'd like to hear some opinions or get some feedback whether you think this is worth pursuing.

For those wanting to try this, in Cargo.toml add:

[dependencies]
libc = "0.2"
ti3-rust = { git = "https://git.imp.fu-berlin.de/koenigl2/ti3-rust.git" }


# Remaining Issues

Some things are lost when using Rust. Since cargo now handles building, the possibility to learn about (Preprocessing) -> Compilation -> Assembly -> Linking is lost. While the goal is not to be CLI compilation magicians, I think understanding this pipeline does help to reason about certain OS behavior. However one might rightfully argue that this is simply too in-depth for a 5 CP second semester course anyway.

1 However this library should not be used in the real-world as it simply wraps the low-level functions in the libc with unsafe blocks and does some ugly casting.

• Have you seen this? JFTR I know almost no rust and still less go. But I have a great interest in this question... – Rusi Jul 18 at 13:20
• @Rusi I like the way goes about certain things, and as Rob nicely points out, it's about composition and simplicity. However, I think it's no surprise that Go was developed at Google with their needs in mind. If we go low-level, we often end up needing to be really... "specific" in a way Go doesn't allow, unfortunately. I think this could be fixed and the idea of Go combined with the specifics and security of Rust, but we're not there yet. Anyhow, for this course I think Rust is the better choice since it forces you to reason about details. – ljrk Jul 18 at 14:09

As a tutor I have taught a student, to create various Unix tools using python. We made: cat, ls, tee, grep, etc. and a simple shell. It did not obscure anything about how operating systems work. It did reduce cognitive load