Page
1
® L O R E N Z O S T O A K E S placeholder not final T H E L I N U X M E M O R Y M A N A G E R EA RL Y AC CE SS The Linux Memory Manager (Early Access) © 2025 by Lorenzo Stoakes
Page
2
The Early Access program lets you read significant portions of an upcoming book while it’s still in the editing and production phases, so you may come across errors or other issues you want to comment on. But while we sincerely appreciate your feedback during a book’s EA phase, please use your best dis-cretion when deciding what to report. At the EA stage, we’re most interested in feedback related to content— general comments to the writer, technical errors, versioning concerns, or other high-level issues and observations. As these titles are still in draft form, we already know there may be typos, grammatical mistakes, miss- ing images or captions, layout issues, and instances of placeholder text. No need to report these—they will all be corrected later, during the copyedit- ing, proofreading, and typesetting processes. Please note that any online resources may not be available until the book is complete. If you encounter any errors (“errata”) you’d like to report, please fill out this Google form so we can review your comments. N O S T A R C H P R E S S E A R LY A C C E S S P R O G R A M : F E E D B A C K W E L C O M E ! The Linux Memory Manager (Early Access) © 2025 by Lorenzo Stoakes
Page
3
THE LINUX MEMORY MANAGER. Lorenzo Stoakes Early Access edition, 2/7/25 Copyright © 2025 by Lorenzo Stoakes. All rights reserved. No part of this work may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording, or by any information storage or retrieval system, without the prior written permission of the copyright owner and the publisher. ISBN-13: 978-1-7185-0446-2(print) ISBN-13: 978-1-7185-0447-9 (ebook) Published by No Starch Press®, Inc. 245 8th Street, San Francisco, CA 94103 phone: +1.415.863.9900 www . nostarch . com; info@nostarch . com Publisher: William Pollock Managing Editor: Jill Franklin For customer service inquiries, please contact info@nostarch . com. For information on distribution, bulk sales, corporate sales, or translations: sales@nostarch . com. For permission to translate this work: rights@nostarch . com. To report counterfeit copies or piracy: counterfeit@nostarch . com. No Starch Press and the No Starch Press iron logo are registered trademarks of No Starch Press, Inc. Other prod- uct and company names mentioned herein may be the trademarks of their respective owners. Rather than use a trademark symbol with every occurrence of a trademarked name, we are using the names only in an editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the trademark. The information in this book is distributed on an “As Is” basis, without warranty. While every precaution has been taken in the preparation of this work, neither the author(s) nor No Starch Press, Inc. shall have any liability to any person or entity with respect to any loss or damage caused or alleged to be caused directly or indirectly by the information contained in it. ® The Linux Memory Manager (Early Access) © 2025 by Lorenzo Stoakes
Page
4
For Sabina, my lovely wife, without whose support this book would not have been possible. For Cherry, Mary, Linus and Jim the cats, who were no help at all*. *. Their emotional support, however, was indispensable. The Linux Memory Manager (Early Access) © 2025 by Lorenzo Stoakes
Page
5
The Linux Memory Manager (Early Access) © 2025 by Lorenzo Stoakes
Page
6
BRIEF CONTENTS Chapter 1: Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Chapter 2: Physical Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Chapter 3: Virtual Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 Chapter 4: Process Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209 Chapter 5: Memory Mapping. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271 Chapter 6: Page Faults . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345 Chapter 7: Reverse Mappings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 435 Chapter 8: Manipulating Userland Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537 Chapter 9: The Page Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 625 Chapter 10: Writeback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 795 Chapter 11: Reclaim and Memory Pressure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 939 Chapter 12: Swap Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1113 Chapter 13: The Out Of Memory (OOM) Killer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1177 Chapter 14: Practical Memory Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1217 Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1287 The Linux Memory Manager (Early Access) © 2025 by Lorenzo Stoakes
Page
7
The Linux Memory Manager (Early Access) © 2025 by Lorenzo Stoakes
Page
8
CONTENTS IN DETA IL 1 INTRODUCTION 1 1.1 Approach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.2 Who Is This Book For? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.3 Book Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 2 PHYSICAL MEMORY 5 2.1 struct page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 2.1.1 Metadata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.1.2 struct slab . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 2.1.3 Page flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 2.2 struct folio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 2.3 Physical memory model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 2.3.1 Sections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 2.3.2 PFN validity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 2.3.3 Converting between PFN and section . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 2.3.4 Page block flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 2.3.5 Looking up struct page/struct folio objects . . . . . . . . . . . . . . . . . . . . . . . . 45 2.4 Nodes and Zones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 2.4.1 Low memory reserve . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 2.4.2 Total reserved pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 2.5 Migrate types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 2.6 GFP flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 2.6.1 Physical address zone modifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 2.6.2 Page mobility and placement hints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 2.6.3 Watermark modifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 2.6.4 Reclaim modifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 2.6.5 Action modifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 2.6.6 Predefined GFP flag combinations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 2.6.7 Memalloc Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 2.7 Buddy allocator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 2.7.1 Algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 2.7.2 Free lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 2.7.3 Per-CPU free Pages (PCPs)/Pagesets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 2.8 Allocator implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 2.8.1 Visualising the allocator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 2.8.2 __alloc_pages() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 2.8.3 rmqueue() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 The Linux Memory Manager (Early Access) © 2025 by Lorenzo Stoakes
Page
9
2.8.4 rmqueue_buddy() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 2.8.5 rmqueue_pcplist() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 2.8.6 Migrate type fallback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 2.8.7 New page preparation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 2.9 Freeing pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 2.9.1 __free_one_page() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 3 VIRTUAL MEMORY 123 3.1 Page Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 3.1.1 Page Table Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 3.1.2 Page Table Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 3.1.3 Page Flag Combinations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 3.1.4 Page Table Traversal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 3.1.5 Page Table Locking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 3.2 The Address Space . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 3.3 Direct Mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 3.3.1 Bootstrapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 3.3.2 Direct Mapping Initialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 3.4 An Introduction to the Transaction Lookaside Buffer . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175 3.5 The Kernel Virtual Memory Allocator (vmalloc) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176 3.5.1 Finding a Free Block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182 3.5.2 Inserting a Newly Allocated Block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195 3.5.3 Physical Allocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 3.5.4 Virtual Mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203 4 PROCESS MEMORY 209 4.1 Overcommit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211 4.2 Userland memory from 50,000 feet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214 4.2.1 Describing userland memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214 4.3 The process address space . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216 4.3.1 mm_struct reference counting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 4.3.2 The initial process address space . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222 4.3.3 Kernel PGD maintenance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224 4.3.4 Process address space locking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228 4.3.5 Process address space flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240 4.4 Virtual Memory Areas (VMAs) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243 4.4.1 VMA flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247 4.4.2 Allocation and freeing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251 4.4.3 VMA layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252 4.4.4 VMA insertion/removal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253 4.4.5 VMA traversal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259 4.5 An introduction to the page cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 4.6 Per-process memory management statistical counters . . . . . . . . . . . . . . . . . . . . . . . . . . 267 x Contents in Detail The Linux Memory Manager (Early Access) © 2025 by Lorenzo Stoakes
Page
10
5 MEMORY MAPPING 271 5.0.1 Program break . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272 5.0.2 mmap() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278 5.0.3 mmap map flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279 5.0.4 mmap kernel implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283 5.0.5 Choosing where to map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 300 5.0.6 Unmapping memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310 5.1 VMA merge and split . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316 5.1.1 VMA merge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316 5.1.2 Mergeability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323 5.1.3 VMA adjust . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325 5.1.4 VMA split . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338 6 PAGE FAULTS 345 6.1 Hardware page fault handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346 6.1.1 Kernel page faults . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348 6.1.2 Userland page faults . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356 6.1.3 Success conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363 6.1.4 Informational . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364 6.1.5 Error conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364 6.2 Page fault handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367 6.2.1 Edge cases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377 6.2.2 Page flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378 6.3 Anonymous page fault . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378 6.3.1 Zero page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381 6.3.2 anon_vma preparation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382 6.3.3 Physical page allocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383 6.3.4 Setting up the PTE entry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384 6.3.5 Adding to the reverse mapping and LRU and setting the PTE . . . . . . . . 385 6.4 Non-anonymous page fault . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385 6.4.1 Folio locks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387 6.5 Non-anonymous read page fault . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388 6.6 Non-anonymous MAP_PRIVATE Copy on Write page fault . . . . . . . . . . . . . . . . . . . . . 393 6.7 Non-anonymous shared write fault . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394 6.8 Shared non-anonymous fault logic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397 6.9 Write-protected page fault . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402 6.9.1 Non-anonymous folios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406 6.9.2 Anonymous folios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406 6.9.3 Folio/PFN sharing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408 6.9.4 Page reuse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413 6.9.5 Folio copying . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414 6.10 Stack expansion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420 6.11 Userland bad area handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 424 6.12 Special mappings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427 Contents in Detail xi The Linux Memory Manager (Early Access) © 2025 by Lorenzo Stoakes
Page
11
7 REVERSE MAPPINGS 435 7.0.1 Anonymous reverse mappings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436 7.0.2 Key points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 442 7.0.3 File reverse mappings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 443 7.0.4 Anonymous reverse mapping types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445 7.0.5 Anonymous reverse mapping initialisation . . . . . . . . . . . . . . . . . . . . . . . . 449 7.0.6 Reusing adjacent VMA’s anon_vma objects . . . . . . . . . . . . . . . . . . . . . . . 454 7.0.7 Connecting anon_vma objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457 7.0.8 Cloning anon_vma objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458 7.0.9 Reusing anon_vma objects on fork . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 460 7.0.10 Forking anon_vma objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 461 7.0.11 VMA split and merge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 463 7.0.12 Folio anon_vma operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 465 7.0.13 File-backed reverse mapping folio operations . . . . . . . . . . . . . . . . . . . . . 472 7.0.14 Unlinking anon_vma objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 474 7.0.15 Walking the reverse mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 476 7.0.16 Walking the VMA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 485 7.0.17 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 493 7.1 Freeing userland memory and the TLB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 493 7.1.1 Unmapping memory mapped regions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494 7.1.2 MMU gather initialisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 495 7.1.3 VMA unmapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 499 7.1.4 Zapping memory ranges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 501 7.1.5 Freeing page tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 516 7.1.6 Flushing the TLB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 524 7.1.7 Freeing pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 532 7.1.8 Lazy TLB mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535 8 MANIPULATING USERLAND MEMORY 537 8.1 Accessing User Memory from the Kernel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537 8.1.1 User Access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 538 8.1.2 Get User Pages (GUP) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 544 8.1.3 Pinning Folios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 546 8.1.4 Follow Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 549 8.1.5 GUP Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 551 8.1.6 Walking Page Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 575 8.1.7 Faulting in Pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585 8.1.8 Fast GUP Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 587 8.1.9 GUP Helper Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 603 8.2 Userland Memory Manipulation APIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 606 8.2.1 mlock() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 606 8.2.2 mprotect() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 612 8.2.3 mremap() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 612 8.2.4 madvise() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 613 xii Contents in Detail The Linux Memory Manager (Early Access) © 2025 by Lorenzo Stoakes
Page
12
9 THE PAGE CACHE 625 9.1 The Virtual File System (VFS) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 626 9.2 A Brief Digression: eXtensible Arrays (xarrays) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 629 9.2.1 API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 641 9.2.2 The Rest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 645 9.3 Reading From a File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 646 9.4 File-Backed Read Faults . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 656 9.5 Reading Page Cache Entries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 670 9.5.1 Reading a Batch of Folios From the Page Cache . . . . . . . . . . . . . . . . . . 671 9.5.2 Reading a Batch of Folios Into the Page Cache . . . . . . . . . . . . . . . . . . . . 676 9.5.3 Reading a Single Folio From the Page Cache . . . . . . . . . . . . . . . . . . . . . 684 9.5.4 Reading a Single Folio Into the Page Cache . . . . . . . . . . . . . . . . . . . . . . 692 9.5.5 Adding Folios to the Page Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 695 9.6 Reading Folios From Disk . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 698 9.7 Readahead . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 701 9.7.1 Synchronous Readahead . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 706 9.7.2 Asynchronous Readahead . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 713 9.7.3 On-Demand Readahead . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 715 9.7.4 Common Readahead Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 724 9.7.5 Physical Readahead . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 729 9.8 Fault-Around . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 731 9.9 Removing Page Cache Entries and Truncation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 738 9.9.1 Removing Folios from the Page Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . 739 9.9.2 Folio Truncation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 743 9.9.3 Unmapping Folios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 754 9.9.4 Dropping Caches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 759 9.9.5 Folio Eviction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 765 9.10 Buffers and Block I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 766 9.10.1 An Introduction to Buffer Heads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 766 9.10.2 blockdev . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 769 9.10.3 Accessing Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 772 9.10.4 Block Writes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 777 9.10.5 Block I/O (BIO) Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 779 9.10.6 Buffer Head I/O Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 780 9.11 Folio Locking and Waiting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 781 10 WRITEBACK 795 10.1 Dirty Tracking in the Kernel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 796 10.2 Marking the Folio Dirty . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 798 10.3 Marking the inode Dirty . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 799 10.4 Page Fault Dirty Tracking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 803 10.5 File Write Dirty Tracking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 810 10.6 Synchronising to Disk . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 816 10.7 sync . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 817 Contents in Detail xiii The Linux Memory Manager (Early Access) © 2025 by Lorenzo Stoakes
Page
13
10.8 syncfs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 819 10.9 fsync . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 821 10.10Writing Back to Disk . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 824 10.11File System and Background Writeback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 842 10.12Flusher Thread Operation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 855 10.13File Writeback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 889 10.14Dirty Throttling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 897 10.15Rate-Limited Dirty Throttling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 902 10.16Dirty Throttle Statistics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 905 10.17Bandwidth Updates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 907 10.18Dirty Position Control Ratio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 911 10.19Dirty Limits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 916 10.20Dirty Poll Interval . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 920 10.21Dirty Rate Limit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 921 10.22Maximum and Minimum Pause Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 926 10.23Core Dirty Throttling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 928 10.24Writeback Chunk Size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 935 10.25Background Writeback Threshold . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 936 11 RECLAIM AND MEMORY PRESSURE 939 11.1 Physical Allocation Slow Path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 941 11.2 LRU Vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 956 11.2.1 struct lruvec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 961 11.2.2 lruvec Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 963 11.3 Direct Reclaim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 967 11.4 Indirect Reclaim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 976 11.4.1 Initialisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 976 11.4.2 kswapd Thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 979 11.4.3 kswapd Sleeping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 983 11.4.4 Node Balancing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 987 11.5 The Reclaim Mechanism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 998 11.5.1 The Scan Control Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 999 11.5.2 A Brief Overview of the Working Set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1004 11.5.3 Shrinking the Node . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1007 11.5.4 Determining Scan Balance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1020 11.5.5 Shrinking LRU Vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1029 11.5.6 Shrinking an Individual LRU List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1037 11.5.7 Shrinking the Active List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1038 11.5.8 Isolating LRU Folios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1042 11.5.9 Shrinking the Inactive List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1048 11.5.10 Reclaim Folio Reference Checking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1065 11.5.11 Reclaim Page Out . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1067 11.5.12 Reclaim Mapping Removal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1070 11.6 Reclaim Throttling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1072 11.6.1 General Reclaim Throttling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1072 xiv Contents in Detail The Linux Memory Manager (Early Access) © 2025 by Lorenzo Stoakes
Page
14
11.6.2 Direct Reclaim Throttling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1077 11.7 Folio Batches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1082 11.7.1 CPU Folio Batches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1083 11.7.2 LRU Rotation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1084 11.7.3 mlock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1084 11.7.4 Folio Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1085 11.7.5 Adding Folios to a Batch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1088 11.7.6 Folio Activation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1093 11.7.7 Folio Rotation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1094 11.7.8 Folio Deactivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1096 11.7.9 File Folio Deactivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1097 11.7.10 Folio Lazy Free . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1099 11.7.11 mlock Folio Batch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1101 11.7.12 Folio Batch Drain . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1106 12 SWAP MEMORY 1113 12.1 The Swap Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1114 12.1.1 Swapper Initialisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1116 12.1.2 Assigning Folios to the Swap Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1118 12.1.3 Page Table Mappings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1119 12.2 Swapping Out . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1122 12.2.1 Adding a Folio to the Swap Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1127 12.2.2 Setting Page Table Swap Entries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1132 12.2.3 Swapping Out to Disk . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1137 12.2.4 Freeing a Swapped Out Folio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1140 12.3 Swapping In . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1144 12.3.1 Page Fault on a Swapped Out Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1145 12.3.2 Looking Up a Folio in the Swap Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . 1155 12.3.3 Reading Swapped Out Folios From Disk . . . . . . . . . . . . . . . . . . . . . . . . . . 1157 12.3.4 Swap Cluster Readahead . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1163 12.3.5 Swap VMA Readahead . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1168 13 THE OUT OF MEMORY (OOM) KILLER 1177 13.1 Causes of Out of Memory Conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1178 13.1.1 Memory Allocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1178 13.1.2 sysrq-f . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1180 13.2 OOM Killer Score Adjustment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1180 13.2.1 OOM Score . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1181 13.3 OOM Killer Alternative Behaviours . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1182 13.3.1 vm.panic_on_oom . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1182 13.3.2 vm.oom_kill_allocating_task . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1182 13.4 Kernel Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1182 13.4.1 Allocating Memory at Risk of OOM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1185 Contents in Detail xv The Linux Memory Manager (Early Access) © 2025 by Lorenzo Stoakes
Page
15
13.4.2 Manual OOM Killer Invocation Via sysrq-f . . . . . . . . . . . . . . . . . . . . . . . . 1188 13.4.3 The Out of Memory Killer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1189 13.4.4 Victim Selection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1196 13.4.5 Victim Killing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1201 13.4.6 OOM Reaper . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1207 14 PRACTICAL MEMORY MANAGEMENT 1217 14.1 Measuring free memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1219 14.1.1 Kernel implementation of MemAvailable . . . . . . . . . . . . . . . . . . . . . . . . . . 1221 14.1.2 Higher order folios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1223 14.1.3 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1224 14.2 Measuring the memory usage of a process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1224 14.2.1 Proportional Set Size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1226 14.2.2 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1226 14.3 Memory mapping using mmap() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1226 14.3.1 Mapping anonymous memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1227 14.3.2 Mapping a file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1228 14.3.3 Private file mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1230 14.3.4 Fixed mappings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1232 14.4 Interpreting Out Of Memory reports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1233 14.4.1 Failed allocation statistics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1237 14.4.2 Stack trace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1238 14.4.3 Global free page statistics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1239 14.4.4 Per-node statistics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1242 14.4.5 Zone-specific statistics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1243 14.4.6 Zone buddy page statistics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1246 14.4.7 Global statistics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1248 14.4.8 Out of memory killer report . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1249 14.5 procfs memory interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1251 14.5.1 A quick tour: Physical memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1254 14.5.2 A quick tour: Virtual memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1259 14.5.3 A quick tour: Page table introspection . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1265 14.6 Memory tunables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1270 14.7 Sharing memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1276 14.7.1 System V shared memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1276 14.7.2 POSIX shared memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1279 14.7.3 Anonymous shared memory across forked processes . . . . . . . . . . . . . . 1281 14.7.4 Sharing memory via memfd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1283 INDEX 1287 xvi Contents in Detail The Linux Memory Manager (Early Access) © 2025 by Lorenzo Stoakes
Page
16
1 INTRODUCT ION The memory management subsystem is arguably the core of the Linux kernel, forming the foundation upon which the rest of the kernel and all of userspace operates. Despite its fundamental nature, it is surpris- ingly complicated and intricate. The Linux Memory Manager explores the Linux kernel’s memory man- agement subsystem in detail. In this chapter we will explore the approach taken, who the book is aimed it, 1.1 Approach Many kernel books take the approach of providing an overview and then hand-waving away details, that is a top-down approach.. The key motivating philosophy of the Linux Memory Manager was to do entirely the opposite—explore each part of the memory management sub- system starting with basic principles, and then work from the bottom-up to form a broader understanding of the topic at hand. Within the kernel there can be no better source of truth than the source code itself, so we explore kernel functionality by exploring its code, which is reproduced in extensive snippets. In effect, this book tries to combine a source commentary with in depth analysis of concepts explored in both extensive discussions of the concepts The Linux Memory Manager (Early Access) © 2025 by Lorenzo Stoakes
Page
17
at hand along side a large number of diagrams which aim to put each con- cept into perspective. As the kernel is constantly evolving and this book necessarily must target a static kernel version, the intent is that by taking this approach, not only will the reader acquire understanding of fundamentals which are unlikely to change, but more importantly develop their skills at exploring kernel source so that they can adapt and update their knowledge to the latest version of the code. 1.2 Who Is This Book For? This book is aimed at developers who already have some fundamental un- derstanding of the C programming language and operating system basics, and have an interest in exploring under the hood to see how Linux manages memory in as much detail as they may want to do so. This spans from that most wonderful of things—a genuinely curious (perhaps aspiring?) kernel hacker to a professional kernel developer, either working with or making use of the memory management subsystem. The intent is to bring out the hidden tribal knowledge within this code- base as much as possible and in the spirit of open source software make it more widely available to curious hackers all over the world! 1.3 Book Overview Chapter 1: Introduction A description of the contents of the book. Chapter 2: Physical Memory A description of how a system’s memory is managed on its most fundamental level—the allocation of its physically installed RAM. Chapter 3: Virtual Memory The why, what and how, page tables, page ta- ble flags, page table sizes, virtual memory layout, direct mapping, ker- nel/userland split and a detailed description of vmalloc(). Chapter 4: Process Memory An overview of how userland memory is structured—mm_struct, Process VMAs, Copy-on-Write and more. Chapter 5: Memory Mapping A description of how memory mapping is performed within the kernel - mmap, brk (used by malloc()) and how map- pings (via VMAs) are split/merged. Chapter 6: Page Faults A detailed examination of how page faults are han- dled and propagated within the kernel. Chapter 7: The Reverse Mapping A detailed look at how the kernel maps raw physical pages of userland memory back to the abstract VMA repre- sentation, in addition to how this is used to free memory. Chapter 8: Manipulating Userland Memory A detailed examination of how the kernel accesses userland memory. Also a brief look at how memory ranges can be manipulated by madvise(). 2 Chapter 1 The Linux Memory Manager (Early Access) © 2025 by Lorenzo Stoakes
Page
18
Chapter 9: The Page Cache A detailed look into the page cache, how it in- teracts with the Linux virtual file system, read-ahead, read-behind and generally a very focused discussion of how the memory subsystem inter- acts with VFS. Chapter 10: Writeback A description of how writeback proceeds both orig- inating from write() operations and memory-mapped files, how dirty data is tracked, how synchronisation functions within the kernel and how dirty throttling is applied. Chapter 11: Reclaim and Memory Pressure A detailed explanation of how reclaim operations, what direct and indirect reclaim are, how it interacts with demand paging, higher order page starvation, etc. Chapter 12: Swap Memory A detailed description of how the swap oper- ations in the kernel and how pages are paged out and paged back in again. Chapter 13: The Out of Memory (OOM) Killer A deep dive into how it works, how to tune it, the what, why and how. Chapter 14: Practical Memory Management A brief overview of practical memory management techniques - procfs interfaces, tuneables, decod- ing out of memory reports and more. Generally a practical ’how to’ for sysadmins/developers. Introduction 3 The Linux Memory Manager (Early Access) © 2025 by Lorenzo Stoakes
Page
19
The Linux Memory Manager (Early Access) © 2025 by Lorenzo Stoakes
Page
20
2 PHYS ICAL MEMORY Physical memory describes all of the memory on a sys- tem which can be addressed arbitrarily by at least one core. Typically this will be in the form of RAM mod- ules but could include other forms of random-access stores. Over the course of this chapter we will explore how the kernel manages, allocates and abstracts this resource. Physical addresses tell the CPU where to find a particular byte of memory. For example, DRAM stores each individual byte on a specific row and col- umn in a specific array known as a bank, accessed by a specific channel on a DIMM stored in a specific slot. The physical address encodes all of this infor- mation. Within the kernel, physical addresses are assigned the phys_addr_t type which is equal to the word size, e.g. for a 64-bit system this is simply an un- signed 64-bit integer. If we were to try to manage every byte of memory individually the over- head associated with trying to keep a track of it would exceed the amount of available memory in the system. This is obviously intractable so we have to compromise and subdivide memory into aggregate blocks, which we call pages. The Linux Memory Manager (Early Access) © 2025 by Lorenzo Stoakes