01 / Reading Guide
Reading Guide
Citation
Bryant, R. E., & O'Hallaron, D. R. (2015). Computer Systems: A Programmer's Perspective (3rd ed.). Pearson.
Chapter Summary
The book has twelve chapters in three parts, plus a short appendix on error handling. The authors state their filter plainly: a topic is included only if it affects the performance, correctness or utility of user-level C programs. Chapters end with a summary and bibliographic notes, most add homework problems, and solutions to the practice problems that appear in the text are collected at the end of each chapter.
Part I: Program Structure and Execution (Chapters 1–6)
Chapter 1: A Tour of Computer Systems
The chapter follows the life cycle of a simple "hello, world" program to introduce the main themes: information as bits plus context, translation of programs by compilation systems, the hardware organization that runs them, caches and the storage hierarchy, the operating system's processes, threads, virtual memory and files, and communication over networks. It ends with three recurring themes: Amdahl's Law, concurrency and parallelism, and abstraction.
Chapter 2: Representing and Manipulating Information
This chapter covers information storage (hexadecimal, word sizes, byte ordering, bit-level and logical operations in C), integer representations (unsigned and two's-complement encodings, conversions, sign extension and truncation), integer arithmetic and floating point (IEEE representation, rounding, floating point in C). The authors stress the consequences for programmers, such as the sum of two positive numbers turning out negative. They note that this is the chapter readers most often find heavy, and the third edition marks where the treatment turns mathematical so that it can be skimmed first.
Chapter 3: Machine-Level Representation of Programs
Here readers learn to read the x86-64 code a C compiler produces: data movement and arithmetic, condition codes, jumps, loops and switch statements, procedures and the run-time stack, arrays, structures and unions, alignment, pointers, using the gdb debugger, buffer overflow and the defences against it, and floating-point code.
Chapter 4: Processor Architecture
The chapter designs a simplified processor around the Y86-64 instruction set. It introduces logic design and the hardware control language HCL, builds a sequential implementation in stages, explains the principles and limits of pipelining, and develops a five-stage pipelined implementation with hazards, exception handling, control logic and performance analysis.
Chapter 5: Optimizing Program Performance
This chapter starts with what optimizing compilers can and cannot do and then removes loop inefficiencies, redundant procedure calls and unneeded memory references. After a model of how modern out-of-order processors work, it covers loop unrolling, multiple accumulators and reassociation, limiting factors such as register spilling and branch misprediction, memory performance, and profiling.
Chapter 6: The Memory Hierarchy
The chapter covers storage technologies (RAM, disks, solid state disks), locality, the memory hierarchy, and cache memories (direct-mapped, set associative and fully associative caches, writes, performance impact of cache parameters). It closes with writing cache-friendly code and the "memory mountain" view of performance.
Part II: Running Programs on a System (Chapters 7–9)
Chapter 7: Linking
Chapter 7 covers compiler drivers, static linking, object files, symbols and symbol resolution, relocation, executable files and loading, dynamic linking with shared libraries, position-independent code, library interpositioning, and tools for manipulating object files.
Chapter 8: Exceptional Control Flow
The chapter introduces exceptions, processes, process control, signals and nonlocal jumps. The authors say that after it, readers will be able to write a simple Unix shell with job control.
Chapter 9: Virtual Memory
The chapter explains physical and virtual addressing, virtual memory as a tool for caching, memory management and protection, address translation, a case study of the Intel Core i7 and Linux memory system, memory mapping, dynamic memory allocation, garbage collection, and common memory-related bugs in C programs.
Part III: Interaction and Communication between Programs (Chapters 10–12)
Chapter 10: System-Level I/O
This chapter covers Unix I/O, files, opening, reading and writing, a robust I/O package for short counts, file metadata, directories, sharing files, I/O redirection and standard I/O. It prepares for the next two chapters.
Chapter 11: Network Programming
The chapter presents the client-server model, networks and the global IP Internet, the sockets interface, web servers, and a Tiny Web Server. The authors call it a thin slice through network programming that gets to a simple web server.
Chapter 12: Concurrent Programming
The final chapter compares concurrency with processes, with I/O multiplexing and with threads, then treats shared variables, synchronization with semaphores, using threads for parallelism, and other issues: thread safety, reentrancy, races and deadlocks.
Appendix A: Error Handling
A short appendix on error handling in Unix systems and error-handling wrappers.
Key Concepts
Part I: Program Structure and Execution (Chapters 1–6)
- Two's-complement and IEEE floating-point representations: why finite bit patterns give surprising arithmetic results.
- Machine-level code and the run-time stack: how C constructs and procedures map to instructions.
- Pipelining: overlapping instruction stages, and the hazards that limit it.
- Locality and the memory hierarchy: why access patterns, not just processor speed, determine performance.
Part II: Running Programs on a System (Chapters 7–9)
- Linking and relocation: how object files and libraries become an executable.
- Exceptional control flow: exceptions, signals and processes as the source of concurrency.
- Virtual memory and dynamic allocation: address translation and the implementation of malloc and free.
Part III: Interaction and Communication between Programs (Chapters 10–12)
- Unix I/O and sockets: building blocks for network programs.
- Concurrent servers: processes, I/O multiplexing and threads compared.
- Synchronization: semaphores, races and deadlocks.
Critical Analysis
Strengths
- A clear organizing idea. The authors contrast a "builder's perspective" with a programmer's perspective and apply a single filter to every topic, which is why linking, signals and malloc are included and detailed adder or bus design is left out.
- Active learning built in. Practice problems follow new concepts with solutions at the end of each chapter, and homework problems carry effort ratings from a few minutes to a ten-hour lab. All code examples were compiled and run on Linux, and the source is available from the book's website.
- Labs from a long-running course. The preface describes the labs used with the book: data, binary bomb, buffer overflow, architecture, performance or cache, shell, malloc and proxy labs. Versions without solutions for self-study are available from the authors' site.
- Support for newcomers to C. "New to C?" notes flag points about the language, and web asides move supplementary material out of the main text.
- Flexible use. The preface maps chapters onto five course types, from a computer organization course to a systems programming course.
Limitations
- Tied to one platform. The book targets x86-64 machine code, the gcc compiler and Linux. Readers on other instruction sets will see different machine code, though the authors say the overall behaviour should be the same.
- Needs C. The authors assume familiarity with C or C++; readers who know only Java will need extra effort, and readers who know only Python, Ruby or Perl are advised to learn C first.
- A simplified processor. Chapter 4 designs a Y86-64 processor, a reduced subset of x86-64, to teach pipelining; it is a teaching design rather than a model of a commercial processor.
- Selective by design. The authors describe the network programming chapter as a thin slice, and the filter leaves out topics such as hardware adder design.
- Dated hardware. The edition dates from 2015 and the processor and cache examples reflect machines of that period.
Where It Fits in the Course
Computer Systems: A Programmer's Perspective views the machine from the software side. Petzold's Code is a narrative introduction for general readers and Nisan and Schocken's The Elements of Computing Systems builds a computer in projects from logic gates upward; either can come before this book. Harris and Harris's Digital Design and Computer Architecture, RISC-V Edition works from hardware upward and has students design a processor, so it pairs with Chapter 4 here. For a graduate-level quantitative study of architecture, Hennessy and Patterson's Computer Architecture: A Quantitative Approach comes later, and Shen and Lipasti's Modern Processor Design develops the out-of-order superscalar processors that Chapter 5 only models in outline.
How to Use This Book
The book is for computer science and engineering students who can program in C or C++ and want to understand what happens beneath their programs. No experience with hardware or assembly language is assumed.
A practical plan, following the preface's course types:
- Core for a programmer-oriented course: Chapters 1 to 3 and 5 to 9, which lead from data representation through machine code, optimization, the memory hierarchy, linking, processes and virtual memory.
- Add for a systems-programming course: Chapters 10 to 12, which build toward a concurrent web server.
- Add for a computer-organization course: Chapter 4 on processor architecture.
- Practice: do the practice problems when each concept appears and attempt the labs, in particular the data, bomb, buffer overflow, cache, shell and malloc labs, with a Linux machine or virtual machine at hand.
