ECE344 Fall 2026 (Sec 1) Lec 2 - Kernels
Watch on YouTube →
Overview
Jon Eyolfson uses a tiny 178-byte x86-64 ELF executable to connect machine code, file descriptors, and system calls, then explains how CPU privilege modes separate user programs from the kernel. He demonstrates Linux tools and interfaces—including readelf, a debugger, strace, /dev, and /proc—and shows how programs in different languages ultimately rely on kernel operations such as write and exit_group.
Key takeaways
- A minimal Unix-style Hello World needs a write system call with descriptor 1, a buffer, and a byte count, followed by exit_group; the example writes 12 bytes.
- System calls cross the user/kernel privilege boundary because user-mode code cannot directly execute privileged instructions or access protected kernel memory.
- ELF headers tell the OS how to load a program and where execution begins; in the example, 120 header bytes precede the instructions.
- strace shows that high-level source code hides substantial runtime activity: the demonstrated C program makes about 30–34 system calls, compared with about 860 for Node.js.
- Unix file descriptors provide a uniform byte-oriented interface: shell redirection works by changing where standard descriptors point, not by changing the program’s write call.
- Linux’s /dev and /proc expose kernel-provided resources through file-like interfaces, including random bytes, discarded output, CPU details, and process descriptor targets.
Chapters
0:00
ECE344 Kernel Lecture Setup and the Hello World Byte Clue
- Jon Eyolfson introduces kernels as the focus of ECE344 Lecture 2.
- The lecture resumes a previous clue: a collection of machine-code bytes represents a working Hello World program.
4:44
A 178-Byte ELF Hello World and the Course’s CPU Architectures
- The x86-64 Hello World executable is only 178 bytes and prints successfully when run.
- The lecture distinguishes x86-64 for many desktops and servers, AArch64 for ARM devices, and RISC-V for the course’s xv6 teaching OS.
- RISC-V connects to earlier coursework; its variants include RV32 and RV64, with extensions such as RV64GC.
7:00
File Descriptors, write, and exit_group
- A file descriptor is an integer index into a process’s OS-managed table, referring to a byte-oriented resource such as a file or terminal.
- The write system call takes a file descriptor, a buffer pointer, and a byte count; exit_group ends the process with a status code.
- By convention, descriptors 0, 1, and 2 are standard input, standard output, and standard error.
- A minimal Hello World writes 12 bytes to descriptor 1, then calls exit_group(0); returning from C main typically invokes process exit on the program’s behalf.
12:30
System-Call ABI: How Programs Request Kernel Services
- An API describes what a function accepts and returns, while an ABI specifies low-level details such as argument placement, return values, and calling convention.
- Linux system calls use CPU registers and a special syscall instruction to cross into the OS, since user programs cannot directly jump into protected kernel memory.
- On x86-64, rax holds the system-call number and six registers carry arguments, limiting this convention to six direct arguments.
- The kernel handles the request and resumes the process after the system call completes.
16:57
ELF Headers, Load Addresses, and Hello World Instructions
- ELF means Executable and Linkable Format; its signature begins with the four bytes 0x7F followed by ELF.
- The example ELF has a 64-byte file header and a 56-byte program header before its 46 bytes of instructions and 12-byte Hello World string.
- The program header requests loading at virtual address 10,000, and the ELF entry point identifies where execution begins.
- The string is length-delimited rather than dependent on a C null terminator, allowing binary data—including zero bytes—to be written.
22:00
Stepping Through a System Call and Defining Kernel Mode
- A debugger shows the Hello World program loading the write system-call number and its three arguments into registers before executing syscall.
- The CPU transfers control to the OS, which writes the 12 bytes to the resource behind descriptor 1, then returns to the program.
- The kernel is the core OS software running in a privileged CPU mode; RISC-V calls the relevant modes U-mode and S-mode, while x86 uses ring 3 and ring 0.
- Privileged instructions let the kernel manage hardware and virtual memory; user-mode programs cannot directly perform those operations.
27:00
System Calls as the User-to-Kernel Boundary
- System calls are the mechanism for transitioning from user mode into kernel mode and requesting protected OS services.
- Jon Eyolfson cites 546 Linux system calls on x86 as the count at the time the lecture slides were prepared.
- Linux’s strace utility exposes a process’s system calls, including the startup execve call and the expected write and exit_group calls.
- strace reports to standard error, so redirecting standard output separately can make its trace easier to inspect.
30:30
strace Reveals the Runtime Work Behind Hello World
- A C Hello World makes roughly 30–34 system calls, including dynamic-library loading, memory setup, and the eventual write and exit_group.
- Node.js running console.log("Hello World") makes about 860 system calls in the demonstrated trace; its output is written through a duplicated descriptor, descriptor 20.
- The Python example makes roughly one-third as many system calls as the Node.js example, while the Rust trace resembles C and also loads the C standard library.
- Regardless of language, visible Hello World output ultimately requires a write to a file descriptor, followed by process termination.
41:00
Kernel Lifetime, Modules, and Unix File Redirection
- The kernel runs for the lifetime of the machine after firmware loads it; Linux kernel modules can add code such as device drivers while it is running.
- Kernel modules execute with privileged access, so malicious or faulty code can inspect memory, kill processes, or force a reboot.
- Unix-like systems use a common open/read/write/close interface for files, terminals, and other resources behind file descriptors.
- Shell redirection changes where descriptors point: > redirects descriptor 1, while 2> redirects descriptor 2.
45:30
Inspecting /dev and /proc, Then Summarizing Process Isolation
- The /dev directory exposes device-like resources, including /dev/zero, /dev/urandom, /dev/null, and pseudo-terminals such as /dev/pts/0.
- The kernel provides virtual files under /proc, including per-process directories, /proc/cpuinfo, and /proc/self/fd for inspecting the current process’s descriptors.
- Reading /dev/zero yields zero bytes, /dev/urandom yields random bytes, and /dev/null returns end-of-file when read.
- Processes run in user mode with independent registers, virtual memory, and file descriptors; system calls cross the hardware privilege boundary, and the kernel manages process isolation.
Summary, takeaways, and chapters were generated by AI from the video's transcript and may contain errors. The video belongs to its creator, Jon Eyolfson.