Itanium C++ ABI 虛擬表詳解:記憶體佈局、多重繼承與虛擬繼承
peter0x44.github.io · 2026-05-27
Itanium C++ ABI 是 Linux/macOS/BSD 等主流平台上 g++ 與 clang++ 採用的二進位介面標準。虛擬表(vtable)是支撐 C++ 執行時期多型的核心機制,本文從記憶體層面完整梳理其結構與分派流程。
基本佈局
vtable 是靜態陣列,存放於 .rodata 段。每個多型物件持有一個隱藏的 vptr,指向 vtable 的「address point」——即第一個函式指標的位置,而非 vtable 起點。vtable 在 address point 之前還有兩個標頭欄位:
- offset-to-top:vptr 所在位置到完整物件起點的距離,用於
dynamic_cast。 - typeinfo 指標:指向 RTTI 型別資訊,支援
dynamic_cast、typeid與例外處理。
以包含 foo()、bar() 的基本類別為例,vtable 結構如下:
Offset 0: offset-to-top = 0
Offset 8: typeinfo pointer
Offset 16: &Base::foo ← address point(vptr 指向此處)
Offset 24: &Base::bar
Offset 32: destructor D1
Offset 40: destructor D0
虛擬函式分派的 x86-64 組合語言本質上是:movq (%rdi), %rax; jmp *(%rax)——從物件載入 vptr,再跳至 vtable 中對應函式指標。
多重繼承
具備多個多型基底類別的物件,每個基底各有一個 vptr。轉換至非主要基底類別的指標時,物件位址可能需要調整(this adjustment)。非主要基底類別使用 non-virtual thunk——編譯器生成的小函式,先以硬編碼常數調整 this,再跳至實際實作。
虛擬繼承
虛擬繼承引入更複雜的 vtable 機制,因為虛擬基底的偏移量在完整物件確定前無法固定:
- vbase offsets:從子物件導航至其虛擬基底的偏移量。
- vcall offsets:從虛擬基底導航回完整物件,供 virtual thunk 使用。
- construction vtables:建構期間臨時安裝的 vtable,確保建構順序中各基底見到正確的偏移量。
- VTT(Virtual Table Table):引導建構過程安裝哪一組 construction vtable 的指標陣列。
這套多層結構使得 C++ 的多型能正確運作,即便在繼承鑽石或多層虛擬繼承等複雜場景下,執行時期的 this 指標仍能準確指向正確的子物件位置。
原始來源:peter0x44.github.io
以 BPF 自訂 Linux 頁面快取逐出策略
LWN.net · 2026-05-22
Linux 核心的頁面快取(page cache)長期使用固定的 LRU 與 multi-generational LRU(MGLRU)演算法管理記憶體頁面的逐出順序。近期一組修補程式提案允許 BPF 程式插入頁面快取決策路徑,讓工作負載針對性地覆寫核心預設策略,無需修改核心或重新開機。
為何需要客製化
不同工作負載對頁面快取的需求差異巨大:資料庫引擎通常自行管理緩衝池(buffer pool),不希望核心快取其讀取的頁面;高頻交易系統可能需要特定熱頁長久駐留;串流處理管線則傾向依序存取後立刻淘汰。這些場景在通用 MGLRU 策略下均有次優表現,過去只能透過 fadvise() 等有限的提示介面間接影響。
BPF 插入機制
修補程式在頁面快取的關鍵決策點引入新的 BPF hook,允許 BPF 程式在頁面被首次加入快取、被存取,或即將被逐出時執行自訂邏輯。BPF 程式可讀取頁面的 inode、偏移量等元資料,並回傳逐出優先權的調整值。由於 BPF 在核心空間以驗證器保護的沙盒中執行,不需要可載入核心模組(LKM)的高風險權限。
影響範圍
此功能若進入主線,資料庫廠商(如 PostgreSQL、MySQL、RocksDB)可在不修改核心的情況下提供更精準的快取暖機與淘汰提示,取代目前相對粗粒度的 MADV_SEQUENTIAL、MADV_WILLNEED 等 madvise 旗標。相關討論目前仍在 Linux 儲存與記憶體管理社群的郵件列表上進行,預計進入核心尚需數個版本的審查週期。
原始來源:LWN.net
Linux 透明大頁面的自動管理改進
LWN.net · 2026-05-26
透明大頁面(Transparent Huge Pages,THP)讓應用程式在不修改程式碼的情況下享受 2 MB 大頁帶來的 TLB miss 減少優勢。然而,核心現有的自動提升(auto-promotion)機制在高記憶體壓力下常與記憶體回收路徑衝突,導致非預期的延遲峰值,迫使許多生產環境將 THP 設為 madvise(僅對明確要求的區域啟用)。
現有問題
當系統記憶體緊張時,核心可能一方面花費 CPU 時間將 4 KB 頁面提升為 2 MB 大頁(khugepaged 背景執行緒),另一方面又因記憶體壓力立刻將大頁拆分(de-fragment)回去,形成浪費。延遲不可預測是 HPC、即時資料庫等場景拒絕開啟 THP 的主要原因。
改進方向
新的修補程式系列針對 khugepaged 引入記憶體壓力感知(memory pressure-aware)邏輯:在系統偵測到記憶體回收壓力上升時,自動降低 THP 提升頻率或暫停提升。修補程式同時改進了 THP 提升與 LRU 演算法(MGLRU)之間的協作,讓提升後的大頁在 LRU 世代中被正確標記,避免被過早淘汰後又觸發再次提升的惡性迴圈。這組改進有望讓 always 模式對更多工作負載安全可用。
原始來源:LWN.net