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.
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.