Sign In Start Free Trial
Account

Add to playlist

Create a Playlist

Modal Close icon
You need to login to use this feature.
  • Book Overview & Buying Systems Programming with Zig
  • Table Of Contents Toc
Systems Programming with Zig

Systems Programming with Zig

By : Mihalis Tsoukalos
close
close
Systems Programming with Zig

Systems Programming with Zig

By: Mihalis Tsoukalos

Overview of this book

Build reliable systems software with Zig through a project-driven approach focused on practical engineering challenges. Guided by UNIX systems engineer & bestselling author Mihalis Tsoukalos, you will learn modern systems programming techniques while creating production-ready applications, UNIX tools, & network services. This book takes you from essential UNIX tooling and build infrastructure to advanced topics such as direct memory access, binary formats, filesystem monitoring, networking, concurrency, asynchronous I/O, & database integration. Through hands-on projects, you will create command-line utilities, TCP and UDP services, HTTP applications, file indexing tools, cache servers, & a domain-specific language interpreter that combines memory management, comptime metaprogramming, parsing, evaluation, & error handling. Each chapter demonstrates how Zig features solve practical systems programming problems. You will work with memory management, process control, synchronization primitives, event-driven architectures, SQLite integration, protocol design, & performance-focused data structures while learning the reasoning behind key engineering decisions. By the end of this book, you will be able to build efficient and maintainable systems software in Zig & confidently apply the language to production projects.
Table of Contents (18 chapters)
close
close
Lock Free Chapter
1
Part 1: Zig Foundations
6
Part 2: Systems Programming in Practice
17
Index

Preface

Welcome to the 1st Edition of Systems Programming with Zig! Systems programming has always been a discipline defined by honesty. Honest about what the hardware can do. Honest about where the memory came from and where it goes. Honest about the cost of every abstraction. For decades, C was the language that embodied that honesty — not because it was elegant but because it hid almost nothing. You saw the pointers. You managed the memory. You felt the machine beneath your fingers.

Zig carries that tradition forward but it does something C never quite managed: it makes the honest path also the convenient one. There is no hidden control flow. There is no global allocator quietly doing work on your behalf. There is no runtime making decisions you did not ask for. What you write is what runs, and the compiler will tell you — loudly, at build time — when what you wrote does not match what the machine requires. That quality, that refusal to let complexity hide in corners, is what makes Zig a genuinely interesting language for systems work rather than merely another contender.

This book is for programmers who want to understand systems, not just use them. We assume you can read Zig code and navigate a UNIX terminal. What we do not assume is that you already know why a TCP echo server blocks on accept(), what the kernel I/O scheduler is doing while your buffered writer accumulates bytes or why the wrong allocator choice in a hot loop can cost you an order of magnitude in throughput. Those are the questions this book is built around.

We build real tools throughout. A tee(1) clone, a Zip file lister, a file watcher backed by platform-specific kernel primitives, a concurrent job scheduler, a production-grade in-memory cache with a custom binary protocol, a note-taking service backed by SQLite3, and, finally, a working interpreter for a small programming language built from scratch. These are not toy examples dressed up as projects. They are the kind of programs that force you to make architectural decisions, feel the consequences of those decisions in the benchmark output, and understand why the systems community settled on the patterns it did.

In the tradition of foundational texts such as The UNIX Programming Environment and The C Programming Language, we frequently pause to examine the why. When we introduce a mutex, we explain what goes wrong without one. When we choose an arena allocator, we benchmark the alternative. When we design a binary protocol, we show what comptime can enforce that a runtime check cannot. The code is a vehicle for understanding engineering tradeoffs, and those tradeoffs are the real curriculum.

Zig 0.16.x arrived with significant changes — new I/O abstractions, a renamed allocator, a reworked networking API — and this book is written against that version throughout. Every code listing compiles and runs on Zig 0.16.0. Where the language made an interesting choice or broke with an older convention, we say so explicitly, because understanding why a language evolves is part of understanding the language.

Systems programming is not a finishing school for programmers who have mastered everything else. It is a way of thinking — about resources, about time, about the gap between what you asked the machine to do and what it actually did. Zig is an exceptionally clear lens for developing that way of thinking, because it refuses to blur the picture.

Thank you for choosing and reading Systems Programming with Zig. Let us dive in and unlock the full potential of Zig together! Happy coding!

Soli Deo gloria

Who this book is for

This book is for programmers who already understand Zig at a basic level and want to use it to do serious systems work, as well as intermediate and experienced systems programmers in Go, Python, Java, C, C++ or Rust who are curious about what Zig brings to the discipline. You do not need to be a Zig expert — a working familiarity with the syntax, the type system, and the basic standard library is enough to follow every chapter from the start.

If you have written application code in higher-level languages and are making your first serious contact with systems programming, some sections will challenge you. The chapters on memory allocators, data structures, and binary protocol parsing in particular assume a willingness to sit with unfamiliar ideas before they fully resolve. A second reading of a difficult section often reveals details that were invisible the first time through. That is not a failure of comprehension — it is how systems knowledge accumulates. Throughout the book, you will find working programs, benchmark results, and exercises grounded in real problems. The tools we build — a job scheduler, a file indexer, a cache server, an interpreter — are not simplified illustrations of the concepts. They are the concepts, expressed in code that compiles and runs. Read them, run them, modify them, break them, and observe what changes! Passive reading will take you only so far in systems programming.

Finally, be prepared for the compiler to argue with you, for benchmarks to produce surprising numbers, and for bugs to hide in places that seem unrelated to where you made the change. This is not a sign that you are doing something wrong. It is the nature of the discipline. Systems programming is an ongoing negotiation between your intentions and the machine's reality, and Zig is unusually honest about where the gaps are. That honesty is uncomfortable at first and invaluable thereafter.

What this book covers

Chapter 1, Building Essential UNIX Tools, introduces Zig as a modern systems language built on the premise of complete programmer control — no hidden control flow, no implicit allocations, and no surprise operator overloads. Rather than explaining Zig syntax from scratch, the chapter assumes working fluency and immediately puts the language to work building three real UNIX utilities: ztee, a tee(1) clone; zwhich, a which(1) clone; and zpass, which demonstrates calling C code directly from Zig via @cImport().

Chapter 2, Systems Infrastructure: Builds, Testing, and Distribution, treats the build process as a first-class systems programming concern. Zig build.zig defines the project build graph using the same syntax as application code, enabling cross-compilation and dependency management without separate tooling. The chapter covers string formatting with std.fmt, memory allocators, unit testing with std.testing, the development of zuuid, and publishing packages using the Zig build system.

Chapter 3, Direct Memory Access and Binary Formats, bridges the gap between abstract variables and the physical machine by exploring Zig pointer mechanics and memory management strategies in depth. The chapter covers pointer arithmetic, custom allocator design, endianness handling, and binary file parsing, culminating in the construction of zunzip, a fully functional Zip file lister built from raw bytes. The chapter closes by benchmarking different memory allocation strategies to connect architectural choices to real-world performance.

Chapter 4, Processing Streams, Buffers, and Data Encoding, shifts focus to I/O efficiency and stream processing. Working through a suite of classic UNIX tools — zcat, zwc, and z64 for Base64 encoding and decoding — the chapter examines buffering strategies, the cost of system calls, SIMD-accelerated data processing, and bitwise encoding logic, closing with benchmarks that quantify the tradeoffs between different reading and writing approaches.

Chapter 5, Navigating Directories and Filesystem Events, explores the mechanics of filesystem interaction at the level of OS primitives. The chapter builds ztree, a recursive directory tree visualizer that correctly handles symbolic links and edge cases, then constructs zwatch, a real-time file monitoring utility backed by Linux inotify or BSD kqueue depending on the platform. The chapter concludes by implementing the core functionality of chmod(1) and chown(8).

Chapter 6, Programming the Network Stack, works up from raw TCP/IP sockets to a complete System Monitor API, building a TCP Echo server and client, a UDP Echo server and client, Docker images for network services, and a minimal HTTP server and client along the way. The chapter treats the network stack as a sequence of increasingly structured abstractions — bytes, frames, protocol, service — and closes by showing how comptime can enforce protocol correctness at compile time rather than runtime.

Chapter 7, Managing Threads, Processes, and Signals, gives direct access to the OS process model through the Zig C interoperability layer. The chapter covers UNIX signal handling with signal(3) and sigaction(2), process creation with fork(2) and exec(3), executing shell commands, and writing a concurrent TCP server and client. All of these concepts converge in zcron, a minimal cron(8)-style job scheduler that detaches from the terminal, manages child processes, and responds correctly to SIGTERM, SIGHUP, and SIGCHLD.

Chapter 8, Orchestrating Concurrency and Synchronization, examines the distinction between concurrency and parallelism and the practical consequences of getting it wrong. The chapter covers mutexes, atomic operations, and condition variables through progressively more demanding examples — race condition avoidance, data corruption prevention, thread pools, ring buffers, and the Producer-Consumer pattern — before applying these tools to zlocate, a concurrent file indexer that distributes filesystem traversal across a worker pool using the Scatter-Gather pattern.

Chapter 9, Implementing Asynchronous I/O, addresses the fundamental scalability problem of synchronous I/O under high concurrency. The chapter establishes the distinction between asynchrony and concurrency, introduces Zig 0.16 async and await model, builds an asynchronous TCP proxy, and refactors it using the std.Io event loop. It closes with a direct performance comparison between the synchronous and asynchronous implementations and includes platform-specific coverage of io_uring on Linux and kqueue on macOS for readers who want to see the kernel machinery directly.

Chapter 10, Building a High-Performance In-Memory Cache Server, constructs zcache, a production-grade in-memory cache built around three cleanly separated layers: an LRU storage engine combining a hash map with an intrusive doubly linked list, a custom binary wire protocol (ZEMP) with fixed-width frame parsing, and a thread-per-connection server. The chapter develops three client tools — a test client, a command-line client, and a benchmark — that together verify correctness, demonstrate usability, and put concrete throughput and latency numbers against the architectural claims.

Chapter 11, Persisting Structured Data with SQLite3, moves from in-memory to persistent storage. The chapter covers reading and writing JSON, parsing structured data into Zig types, and generating JSON from in-memory structures. It then connects to SQLite3 through the Zig C interoperability layer, building a complete note-taking service with an HTTP API and a dedicated client, demonstrating how battle-tested C libraries can be integrated into Zig programs without sacrificing compile-time safety.

Chapter 12, Developing a Domain-Specific Language, closes the book by building a small interpreted programming language called zcalc from scratch in Zig. The chapter implements all three pillars of an interpreter — a Lexer that transforms raw text into tokens, a Parser that structures those tokens into an Abstract Syntax Tree, and an Evaluator that executes the tree — and wraps them in an interactive REPL. Building a language from scratch in Zig demonstrates how comptime, explicit memory management, and the standard library combine to tackle one of the most intellectually demanding problems in software.

To get the most out of this book

This book requires a machine running macOS, Linux, or any UNIX-like operating system with Zig 0.16.0 or later installed. Most of the code examples rely on POSIX interfaces — fork(2), signal(3), kqueue, and similar — that are not available on Windows, so a UNIX environment is a genuine requirement rather than a recommendation. Familiarity with the command line, the filesystem, and basic git(1) usage is assumed throughout.

This book is written against Zig 0.16.0, and every code listing has been verified against that version. Install Zig 0.16.0 or later from the official Zig website at https://ziglang.org/download/ or use a version manager such as mise or zigup to keep your installation current. Verify your installation with zig version before running any of the examples. If you are running a version newer than 0.16.0, the vast majority of the code will compile without changes, but be aware that Zig is a fast-moving language and any release may introduce breaking changes — particularly in the I/O and networking APIs that several chapters depend on heavily. The asynchronous I/O chapter in particular uses std.Io features introduced in 0.16, so anything earlier than that will not work regardless of how close the version number appears.

The source code for every example in this book is available on GitHub. Clone the repository and follow along — reading code is useful, but running it, modifying it, and breaking it deliberately is where the real understanding comes from. When a benchmark produces a number, change a parameter, and see what moves. When a comptime assertion fires, read the error carefully before fixing it. The compiler feedback is part of the learning experience, not an obstacle to it.

Systems programming rewards patience and curiosity in equal measure. Zig is a language that gives you the full picture of what the machine is doing, and that picture is worth spending time with.

Download the example code files

The code bundle for the book is hosted on GitHub at https://github.com/mactsouk/zigSP. We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!

Download the color images

We also provide a PDF file that has color images of the screenshots/diagrams used in this book. You can download it here: https://packt.link/gbp/9781807426439.

Conventions used

There are a number of text conventions used throughout this book.

CodeInText: Indicates code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles. For example: Mount the downloaded WebStorm‑10*.dmg disk image file as another disk in your system.

A block of code is set as follows:

const std = @import("std");

pub fn main(_: std.process.Init.Minimal) !void {
    std.debug.print("Hello {s}!\n", .{"World"});
}

When we wish to draw your attention to a particular part of a code block, the relevant lines or items are set in bold:

    const pathEnv = init.environ_map.get("PATH") orelse {
        std.debug.print("Error: PATH variable not found\n", .{});
        return;
    };

Any command-line input or output is written as follows:

$ zig run ch01/stdArrayList.zig
Adding numbers 0, 10, 20, 30, 40...
Modified index 2 to 999.
List contents: 0 10 999 30 40
Popped last item: 40
Final count: 4

Bold: Indicates a new term, an important word, or important information. For instance, words in menus or dialog boxes appear in the text like this. For example: The wordByWord() function uses regular expressions to separate the words found in each line of the input file.

Warnings or important notes appear like this.

Get in touch

Feedback from our readers is always welcome.

General feedback: Email [email protected] and mention the book's title in the subject of your message. If you have questions about any aspect of this book, please email us at [email protected].

Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you reported it to us. Please visit http://www.packtpub.com/submit-errata, click Submit Errata, and fill in the form.

Piracy: If you come across any illegal copies of our works in any form on the internet, we would be grateful if you would provide us with the location address or website name. Please contact us at [email protected] with a link to the material.

If you are interested in becoming an author: If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, please visit http://authors.packtpub.com.

Join us on Discord!

Read this book alongside other users, developers, experts, and the author himself.

Ask questions, provide solutions to other readers, chat with the authors via Ask Me Anything sessions, and much more. Scan the QR or visit the link to join the community.

Discord QR

https://packt.link/deep-engineering-golang

CONTINUE READING
83
Tech Concepts
36
Programming languages
73
Tech Tools
Icon Unlimited access to the largest independent learning library in tech of over 8,000 expert-authored tech books and videos.
Icon Innovative learning tools, including AI book assistants, code context explainers, and text-to-speech.
Icon 50+ new titles added per month and exclusive early access to books as they are being written.
Systems Programming with Zig
notes
bookmark Notes and Bookmarks search Search in title playlist Add to playlist download Download options font-size Font size

Change the font size

margin-width Margin width

Change margin width

day-mode Day/Sepia/Night Modes

Change background colour

Close icon Search
Country selected

Close icon Your notes and bookmarks

Confirmation

Modal Close icon
claim successful

Buy this book with your credits?

Modal Close icon
Are you sure you want to buy this book with one of your credits?
Close
YES, BUY

Submit Your Feedback

Modal Close icon
Modal Close icon
Modal Close icon