Skip to main content

Command Palette

Search for a command to run...

System Programming: OS Design and Implementation

Updated
5 min read
System Programming: OS Design and Implementation

Start the MIT 6.1810 Fall2025 Course

So… here’s an update on my learning path.

2023 – 2024: Building a Modern Computer from First Principles (aka Nand2Tetris). I studied the fundamentals of computer architecture; from logic gates and the CPU to the operating system and compiler.

Mid 2025: Introduction to Networking Basics.

Late 2025 – :

I want to learn more about OS internals, especially the Linux kernel and similar topics. So, some days ago, I started the MIT 6.1810 course on Design and Implementation of Operating Systems.

The course is based on xv6, a simple Unix-like teaching operating system. The goal is to study OS concepts by extending xv6.

What’s good about this course:

  • It’s well structured and has a clear schedule. (This year’s session started in September 2025 and is expected to end in December 2025.)

  • It combines theory with practical labs, so you don’t just read; you build as well.

I’ll spend some nights and weekends working on it, enjoy the process, and share updates about my progress here.

I’m currently working on the Week 1 assignment (Lab: Utilities), where we’re implementing Unix-like utilities using the xv6 API.

By the way, MIT offers really well-structured courses on various topics in Computer Science.

MIT 61.810 Fall 2025 (Operating System Engineering) link:[https://pdos.csail.mit.edu/6.1810/2025/overview.html]

Update [07 November 2025]

Lectures

I just finished week 1 of the course. This week, I read Chapter 1: Operating System Interface of the book on xv6. This chapter introduces:

  • The xv6 system calls, such as open, which "opens" a file by returning a file descriptor, and fork, which creates a process.

  • How processes behave, including how to create a child process and execute a command.

  • Importantly, what a file descriptor is (an entry in a table for each process that lists files opened by the process), which allows a process to read or write.

  • A method for processes to communicate (Inter-Process Communication): Pipes, which use file descriptors.

I also read the chapters on Pointers (Arrays, Characters, Structs) from The C Programming Language (Second Edition) by Kernighan and Ritchie (K&R) to refresh key concepts about manipulating pointers.

Then there are the assignments or labs.

Lab Assignments: Unix utilities

The labs focused on writing Unix-like utilities. Here are a few, along with brief descriptions::

  • sixfive (not so easy): For each input file, sixfive must print all the numbers in the file that are multiples of 5 or 6. Number are a sequence of decimal digits separated by characters in the string " -\r\t\n./,".

  • memdump (not so easy): Implement the function memdump(char fmt, char data). memdump()'s purpose is to print the contents of the memory pointed to by data in the format described by the fmt argument.

  • find (not easy): Write a simple version of the UNIX find program for xv6: find all the files in a directory tree with a specific name.

  • pingpong (easy and from Fall 2020): Write a program that uses UNIX system calls to ping-pong a byte between two processes over a pair of pipes, one for each direction

These labs were not too difficult and had clear instructions, but I often felt stuck and unsure of what to do. However, after reading chapter 1 of the xv6 book multiple times and reviewing the source code of some existing utilities, I completed them. Here are a few things to remember (and I'm not ready to forget them)::

  1. When creating a child with the fork system call, don't forget to use wait in the parent. This ensures that the parent waits for the child to finish executing. This way, both the parent and child code will run properly.
  •   if (fork() == 0) // Child
      {
          write(1, "hello ", 6);
          exit(0);
      }
      else // Parent
      {
          wait(0); // Don't forget to wait here so child can execute
          write(1, "world\n", 6);
      }
    

    Forgetting this, make me stuck on the pingpong task.

  1. When we define an array of int and another of char, like int tab_1[5] and char tab_2[5], we know that tab_1 and tab_2 are pointers to the first element ([0]) of the array. Also, tab_1[1] is equivalent to *(tab_1 + 1), and the same applies to tab_2[1], which is equivalent to *(tab_2 + 1)..

    • But if we assume that the memory address of tab_1 is 4000 and the address of tab_2 is 5000, what will be the address of tab_1[1] and tab_2[2]? The address of tab_1[1] will be 4000 + 4 bytes = 4004, not 4001, since sizeof(int) = 4 bytes on most modern 32-bit/64-bit computers..

      Why? Because tab_1 is a series of contiguous memory addresses that store integers, each with a size of 4 bytes (sizeof(int)). To move from one address or index to the next in the array, you need to step by 4 bytes. So, you move 4 bytes at a time. tab_1[0] occupies the memory blocks from 4000 to 4003, and tab_1[1] starts at 4004.

      The same rule applies to tab_2, but here sizeof(char) \= 1, so the address of tab_2[1] will be 5000 + 1 byte = 5001.

      The rule is simple: New Address = Start Address + (N * sizeof(Type))

    • But here's another question: when we use *(tab_1 + 1) or tab_1[1], how does the compiler know to add N * sizeof(Type) to the initial address? Well, this is done at compile time when the compiler generates the assembly code. It uses a table called the Symbol Table, which holds information about variables, functions, and other elements in our code. This allows it to check the data type and perform the appropriate calculations..

From Gemini

When the compiler reads your source code, it builds an internal data structure called the Symbol Table. This table tracks every identifier (variable, function, type, etc.) in your program and records all its key attributes, including its data type.

For a pointer variable declared as int *p; the Symbol Table records that p is a pointer to an int.

Done for now, see you next time!

It's good to write the utility and get back into C to remember these concepts before diving into OS.

I'm starting Week 2 of the course.

By the way, here's my GitHub repo for the lab course: https://github.com/TawalMc/MIT-6.1810Fall2025-xv6