Chapter 27 — A Second User Program for Safe Background Execution

This entry is part 24 of 25 in the series Writing A Linux Style Operating System From Scratch

In Chapter 26, we added: That gave us a real background process path. But our only user program, demo, waits for terminal input: That makes it awkward for runbg, because a background process can compete with the monitor for keyboard input. This chapter adds a second embedded user program: counter does not read from stdin.

Chapter 26 — Process Table, ps, runbg, and wait PID

Chapter 26 — Process Table, ps, runbg, and wait PID
This entry is part 23 of 25 in the series Writing A Linux Style Operating System From Scratch

In Chapter 25, the monitor gained an embedded program registry and a foreground run command: That gave us an exec-like path, but only in foreground mode: This chapter adds the next process-management layer: After this chapter, the monitor will support: The kernel still does not have job control, signals, or a filesystem, but it now

Chapter 24 — User argc / argv and a Real Initial Stack

Chapter 24 — User argc / argv and a Real Initial Stack
This entry is part 22 of 25 in the series Writing A Linux Style Operating System From Scratch

In Chapter 23, we crossed another major boundary: But the user program still started like this: That is not how we want user programs to look long-term. This chapter adds a real initial user stack with: Then crt0.S will pass those arguments to: This moves us closer to a normal process startup model. ELF process

Chapter 23 — Building a Real User C Program and Embedding Its ELF

Chapter 23 — Building a Real User C Program and Embedding Its ELF
This entry is part 21 of 25 in the series Writing A Linux Style Operating System From Scratch

In Chapter 22, the kernel gained a first ELF32 loader. That was a big step, but our test ELF was still built by hand inside process.c: This chapter removes that artificial piece. We will add a tiny userland build pipeline: GNU objcopy is specifically designed to copy and transform object files between formats; we will

Chapter 21 — Process Teardown and Address-Space Cleanup

Chapter 21 — Process Teardown and Address-Space Cleanup
This entry is part 20 of 25 in the series Writing A Linux Style Operating System From Scratch

In Chapter 20, we added the TOYEXE loader: But there is still a lifecycle problem. The process can exit, but we are not yet reclaiming everything it owns. Right now this leaks: This chapter closes that loop. After this chapter, the process lifecycle becomes: The milestone output will look like: 1. What this chapter adds

Chapter 20 — A Tiny Executable Format and User Program Loader

Chapter 20 — A Tiny Executable Format and User Program Loader
This entry is part 5 of 25 in the series Writing A Linux Style Operating System From Scratch

In Chapter 19, we gave each process its own address space: That was a major architectural milestone. But our user program is still not really “loaded.” We are still building a TOYEXE image inside process.c and handing it to the loader. This chapter adds a small executable format before jumping to ELF. We will call

Chapter 19 — Per-Process Address Spaces and CR3 Switching

Chapter 19 — Per-Process Address Spaces and CR3 Switching
This entry is part 19 of 25 in the series Writing A Linux Style Operating System From Scratch

In Chapter 18, user programs gained a much more realistic syscall interface: But all user processes still shared the same page directory. That means every process saw the same user mappings: This chapter gives each process its own address space. The new model becomes: When the scheduler switches between processes, it will also switch CR3.

Chapter 18 — File-Descriptor Syscalls and a Tiny User-Mode Console Program

Chapter 18 — File-Descriptor Syscalls and a Tiny User-Mode Console Program
This entry is part 18 of 25 in the series Writing A Linux Style Operating System From Scratch

In Chapter 17, we added the first minimal process object: That was a big step, but the syscall interface was still a little too artificial. This chapter makes user programs feel more like real programs by adding a tiny file-descriptor-style interface: We will update SYS_WRITE to use a file descriptor, add SYS_READ, and run a

Chapter 17 — Minimal Processes, User Memory Copying, and More Robust Syscalls

Chapter 17 — Minimal Processes, User Memory Copying, and More Robust Syscalls
This entry is part 17 of 25 in the series Writing A Linux Style Operating System From Scratch

In Chapter 16, we proved the biggest privilege milestone so far: But the user-mode test was still mostly a raw thread experiment. The kernel did not yet have a real object representing a user program. This chapter adds the first process abstraction. A process will own: We will also add safer user-memory access helpers: and

Chapter 16 — Entering User Mode and Returning Through Syscalls

Chapter 16 — Entering User Mode and Returning Through Syscalls
This entry is part 16 of 25 in the series Writing A Linux Style Operating System From Scratch

We now have an interactive, preemptive kernel with memory management, blocking, synchronization, keyboard input, terminal editing, and a monitor. So far, however, everything runs in ring 0. That means every thread has full kernel privilege. There is no separation between kernel code and user code yet. This chapter adds the first user-mode milestone: Intel’s IA-32