Demand paging 是 Linux 記憶體管理裡很核心的策略。它的想法很直接:不要在 process 要求位址空間時就立刻付出所有成本,而是等它真的讀寫某個 page,再配置或載入那個 page。這讓系統可以更有效使用 RAM,也讓很多看似很大的配置不會立刻變成實際壓力。
舉例來說,程式啟動時會載入 executable 和 shared library,但不代表所有程式碼和資料都馬上進 RAM。kernel 可以先建立 VMA,等 CPU 執行到某段程式碼或讀到某段資料時,page fault 才把對應 page 載入。很多程式其實只會用到 library 的一部分,demand paging 就避免了不必要的載入。
malloc() 也常讓人誤會。使用者程式向 allocator 要一大塊空間,allocator 可能再向 kernel 要一段虛擬位址範圍。但只要程式還沒有真的寫入每個 page,實體 RAM 不一定全部配置。這也是為什麼某些程式看起來 VSZ 很大,但 RSS 沒有同步變大的原因。
Demand paging 也和 overcommit 有關。Linux 可以允許 process 承諾使用比目前實體 RAM 更多的虛擬記憶體,因為不是所有承諾都會同時變成實際使用。這讓系統更有彈性,但也帶來風險:如果很多 process 真的同時碰到那些 page,系統可能進入 memory pressure,甚至觸發 OOM。
這個策略的代價是第一次存取會比較慢。第一次碰到 page 時,page fault handler 需要介入,可能只是配置零頁,也可能需要從檔案或 swap 讀資料。之後 page 已經在 RAM 且 page table 建好,存取才會變快。所以有些 latency-sensitive 系統會做 prefault 或 memory locking,避免關鍵路徑突然遇到 page fault。
觀察 demand paging 時,可以看 minor fault 和 major fault。minor fault 通常代表不需要磁碟 I/O 的 fault;major fault 則代表需要讀取 backing store,成本更高。兩者都不是單純的錯誤數字,而是系統延遲配置和載入策略留下的痕跡。
下一篇會看 copy-on-write。Demand paging 解釋了「用到才配置」,COW 則更進一步:連複製也可以先不複製,等真的有人寫入時再處理。