Back to Courses
IN3000 — Operating Systems
IN3000 2024

IN3000 — Operating Systems

Advanced OS coursework in C and x86 Assembly — process management, memory management, synchronization, interrupt handling, and building core OS components close to hardware with Bochs and GDB.

  • C
  • x86 Assembly
  • Operating Systems
  • Bootloader
  • Scheduling
  • System Calls
  • IPC
  • Virtual Memory
  • File Systems
  • Bochs
  • GDB

IN3000 – Operating Systems at UiO. The most demanding course in the CS programme — you build core OS components yourself, in C and x86 assembly, running on a real x86 emulator.

Course structure

The course proceeds from hardware up through the kernel to user-space interfaces. Each assignment targets a specific OS subsystem.

Topics and assignments

Bootloader and protected mode

  • Writing a bootloader in x86 assembly that runs in real mode, sets up the A20 line, loads the GDT, and switches to 32-bit protected mode
  • Disk I/O via BIOS INT 13h before any OS support is available
  • Loading the kernel from disk into memory at a specific address

Interrupt handling

  • Interrupt Descriptor Table (IDT) setup — registering handler functions for hardware and software interrupts
  • Implementing the 8259 PIC (Programmable Interrupt Controller) — enabling/disabling IRQs, EOI signalling
  • Timer interrupt (IRQ0) as the driver for preemptive scheduling
  • Exception handlers: page faults, general protection faults, divide-by-zero

Process management

  • Process Control Block (PCB) — data structure holding state (registers, stack pointer, program counter, process ID, status)
  • Context switching — saving and restoring register state in assembly, switching stacks
  • Round-robin scheduler and priority scheduling implementations
  • Process states: running, ready, blocked, terminated

Memory management

  • Segmentation — GDT entries for code/data segments with privilege levels (ring 0 and ring 3)
  • Paging — page directory, page tables, CR3 register, TLB management
  • Virtual memory — each process gets its own address space; kernel maps at high addresses
  • Demand paging and page fault handling

Synchronization

  • Spinlocks — busy-wait with atomic test-and-set
  • Semaphores — blocking synchronization with wait queues
  • Classic concurrency problems: producer-consumer, readers-writers, dining philosophers

System calls

  • Software interrupt (INT 0x80) — user-to-kernel transition with privilege elevation
  • Implementing syscall dispatch table
  • Writing write(), read(), fork(), exec(), exit() syscall implementations

IPC

  • Shared memory — two processes communicating through a common memory region
  • Message queues — sending and receiving kernel-mediated messages
  • Pipes — producer-consumer with a circular buffer in kernel space

File systems (conceptual + partial implementation)

  • inode model: metadata separated from data blocks
  • Directory entries, hard links vs symbolic links
  • Block allocation strategies: contiguous, linked, indexed (inode with direct + indirect blocks)

Tools used

  • Bochs — x86 PC emulator that simulates hardware faithfully; allows pausing mid-boot and inspecting registers
  • GDB with Bochs stub — setting breakpoints inside the bootloader and kernel, stepping through assembly
  • NASM — assembler for x86 assembly code
  • GCC cross-compiler — compiling C without a runtime for bare-metal targets

What this course is really about

Most programmers never think about what happens when their code calls malloc() or writes to a file — the OS just handles it. This course removes that abstraction. Understanding virtual memory, the privilege model, and how context switching works makes you a fundamentally better programmer, even if you never write another line of kernel code.