ECE 391 Operating System Development

ECE 391: Computer Systems Engineering – Final Project (Team)

  • Tech Stack: C, x86 Assembly, GCC, GDB, QEMU
  • Platform: x86 Protected Mode, Custom Kernel

Overview

As a team of four, we built a functional Unix-like operating system kernel from scratch for x86 protected mode. The project covered the full stack of OS development—from memory management and task scheduling to file system interaction and hardware-level device drivers. We deployed and tested the OS using QEMU and debugged it with GDB.

Collaborative Focus

Our team divided responsibilities across major subsystems. One member focused on memory and paging, another implemented device and terminal drivers, and I worked primarily on the file system and process control structures. We coordinated our integration weekly, using Git for version control and debugging together during late-night QEMU/GDB sessions.

Key Features

  1. System Call Layer: Implemented syscall wrappers and handlers for user-space apps to interact with kernel functionality (`read`, `write`, `open`, `close`, `execute`, etc.).
  2. Paging Mechanism: Enabled 4MB paging to isolate user and kernel memory, configured via CR3 and page directory structures.
  3. Multi-Terminal Support: Enabled seamless switching between three independent terminals, each maintaining its own shell and screen state.
  4. Preemptive Scheduling: Built a round-robin scheduler triggered via timer interrupts to cycle between user processes.
  5. File System Implementation: Developed a FAT-like read-only file system with directory and inode-based access to program binaries and text files.

What We Learned

  1. Low-Level Collaboration: Worked effectively as a team to integrate assembly, C, and hardware interactions.
  2. Interrupt-Driven Architecture: Gained hands-on experience with IRQs, PICs, and timer-based process switching.
  3. Protected Memory: Used paging to protect kernel and user-space memory with privilege enforcement.
  4. Process Control: Built a minimal process table, TSS usage, and shell launching framework.
  5. Debugging in QEMU: Used GDB extensively to resolve low-level memory and pointer bugs, including stack issues and IDT faults.

Conclusion

ECE 391 was one of the most challenging and rewarding courses in our undergraduate curriculum. By building a kernel-level OS from scratch, we developed strong systems-level thinking and a practical understanding of how hardware interfaces with software—skills that have carried forward into real world software engineering. The project taught us the importance of low-level programming, debugging, and collaborative development in creating robust systems.