這個檔案包含 Zircon 的記憶體管理和診斷資訊,並說明檢查程序和系統記憶體用量的方法。
程序可使用記憶體的方式有 3 種:
- 以堆積、執行緒堆疊、可執行程式碼 + 資料的形式對應記憶體。此記憶體會以 VMAR 表示,並會保留對 VMO 的參照。程式設計師通常會透過記憶體位址與這個記憶體互動。
- 獨立 VMO。這些是未透過 VMAR 對應的記憶體頁面組合。程式設計師會透過帳號代碼與這個記憶體互動,通常會發出 vmo_read 和 vmo_write。
- 核心記憶體,採用對核心物件的處理常式的形式。
Fuchsia 遵循過度修訂模型:程序在任何特定時刻分配的記憶體會超過可以滿足的條件,而且當記憶體頁面由核心即時分配 (有線) 寫入時,程序會因此分配到更多記憶體。
使用者空間記憶體
哪些程序會使用所有記憶體?
傾印程序記憶體總用量
使用 ps
工具:
$ ps
TASK PSS PRIVATE SHARED NAME
j:1028 32.9M 32.8M root
p:1043 1386.3k 1384k 28k bin/devmgr
j:1082 30.0M 30.0M zircon-drivers
p:1209 774.3k 772k 28k /boot/bin/acpisvc
p:1565 250.3k 248k 28k driver_host
p:1619 654.3k 652k 28k driver_host
p:1688 258.3k 256k 28k driver_host
p:1867 3878.3k 3876k 28k driver_host
p:1916 24.4M 24.4M 28k driver_host
j:1103 1475.7k 1464k zircon-services
p:1104 298.3k 296k 28k crashlogger
p:1290 242.3k 240k 28k netsvc
p:2115 362.3k 360k 28k sh:console
p:2334 266.3k 264k 28k sh:vc
p:2441 306.3k 304k 28k /boot/bin/ps
TASK PSS PRIVATE SHARED NAME
PSS (比例共用狀態) 是一個位元組數,可評估程序中對應實體記憶體消耗的位元組數。其值為 PRIVATE +
(SHARED / sharing-ratio)
,其中 sharing-ratio
是以這個程序共用各頁面的程序數量為計算依據。
也就是說,假設有 4 個程序共用單一頁面,則這四個程序的 PSS
都會包含該網頁的 1/4 位元組。如果兩個程序共用不同的頁面,則每個程序會獲得該頁面的 1/2 位元組。
PRIVATE 是此程序僅對應的位元組數量。也就是說, 其他程序不會繪製這個記憶體請注意,系統不會將未對應的私人 VMO 列入計算。
SHARED 是這項程序和至少一個其他程序所對應的位元組數。請注意,這並未計入未對應的共用 VMO。也不會指出共用記憶體的處理程序數量:可能為 2 個,可以是 50 個。
視覺化呈現記憶體用量
如果您有 Fuchsia 版本,可以使用樹狀圖來呈現系統的記憶體用量。
在主體機器上,從 Fuuchsia 結帳功能的根目錄執行下列指令:
./scripts/fx shell memgraph -vt | ./scripts/memory/treemap.py > mem.html
在瀏覽器中開啟
mem.html
。
memgraph
工具會產生系統工作和記憶體資訊的 JSON 說明,然後由 treemap.py
指令碼剖析。-vt
表示在輸出內容中納入 VMO 和執行緒。
傾印程序的詳細記憶體對應圖
如果您想瞭解特定程序為何使用這麼多記憶體,可以在其 koid 上執行 vmaps
工具 (執行 ps 時顯示的 ID),查看該程序對應到記憶體的項目。
$ vmaps help
Usage: vmaps <process-koid>
Dumps a process's memory maps to stdout.
First column:
"/A" -- Process address space
"/R" -- Root VMAR
"R" -- VMAR (R for Region)
"M" -- Mapping
Indentation indicates parent/child relationship.
資料欄標記:
:sz
:項目的虛擬大小,以位元組為單位。並非所有頁面都需要實體記憶體備份。:res
:項目中的「常駐」記憶體量,以位元組為單位,亦即支援項目的實體記憶體量。這個記憶體可能僅供私人 (僅可透過此程序存取) 或由多個程序共用。:vmo
:對應至這個區域的 VMO 的koid
。
$ vmaps 2470
/A ________01000000-00007ffffffff000 128.0T:sz 'proc:2470'
/R ________01000000-00007ffffffff000 128.0T:sz 'root'
...
# This 'R' region is a dynamic library. The r-x section is .text, the r--
# section is .rodata, and the rw- section is .data + .bss.
R 00000187bc867000-00000187bc881000 104k:sz 'useralloc'
M 00000187bc867000-00000187bc87d000 r-x 88k:sz 0B:res 2535:vmo 'libfdio.so'
M 00000187bc87e000-00000187bc87f000 r-- 4k:sz 4k:res 2537:vmo 'libfdio.so'
M 00000187bc87f000-00000187bc881000 rw- 8k:sz 8k:res 2537:vmo 'libfdio.so'
...
# This 2MB anonymous mapping is probably part of the heap.
M 0000246812b91000-0000246812d91000 rw- 2M:sz 76k:res 2542:vmo 'mmap-anonymous'
...
# This region looks like a stack: a big chunk of virtual space (:sz) with a
# slightly-smaller mapping inside (accounting for a 4k guard page), and only a
# small amount actually committed (:res).
R 0000358923d92000-0000358923dd3000 260k:sz 'useralloc'
M 0000358923d93000-0000358923dd3000 rw- 256k:sz 16k:res 2538:vmo ''
...
# The stack for the initial thread, which is allocated differently.
M 0000400cbba84000-0000400cbbac4000 rw- 256k:sz 4k:res 2513:vmo 'initial-stack'
...
# The vDSO, which only has .text and .rodata.
R 000047e1ab874000-000047e1ab87b000 28k:sz 'useralloc'
M 000047e1ab874000-000047e1ab87a000 r-- 24k:sz 24k:res 1031:vmo 'vdso/stable'
M 000047e1ab87a000-000047e1ab87b000 r-x 4k:sz 4k:res 1031:vmo 'vdso/stable'
...
# The main binary for this process.
R 000059f5c7068000-000059f5c708d000 148k:sz 'useralloc'
M 000059f5c7068000-000059f5c7088000 r-x 128k:sz 0B:res 2476:vmo '/boot/bin/sh'
M 000059f5c7089000-000059f5c708b000 r-- 8k:sz 8k:res 2517:vmo '/boot/bin/sh'
M 000059f5c708b000-000059f5c708d000 rw- 8k:sz 8k:res 2517:vmo '/boot/bin/sh'
...
您也可以使用 zxdb 中的
aspace
指令顯示記憶體對應。
傾印與程序相關聯的所有 VMO
vmos <pid>
這也會顯示未對應的 VMO,其中 ps
和 vmaps
目前並未列入考量。
也會顯示特定 VMO 是否為子項,以及其父項的 koid。
$ vmos 1118
rights koid parent #chld #map #shr size alloc name
rwxmdt 1170 - 0 1 1 4k 4k stack: msg of 0x5a
r-xmdt 1031 - 2 28 14 28k 28k vdso/stable
- 1298 - 0 1 1 2M 68k jemalloc-heap
- 1381 - 0 3 1 516k 8k self-dump-thread:0x12afe79c8b38
- 1233 1232 1 1 1 33.6k 4k libbacktrace.so
- 1237 1233 0 1 1 4k 4k data:libbacktrace.so
...
- 1153 1146 1 1 1 883.2k 12k ld.so.1
- 1158 1153 0 1 1 16k 12k data:ld.so.1
- 1159 - 0 1 1 12k 12k bss:ld.so.1
rights koid parent #chld #map #shr size alloc name
欄數:
rights
:如果程序透過控點指向 VMO,此欄會顯示該控點具備零或多個以下的權利:r
:ZX_RIGHT_READ
w
:ZX_RIGHT_WRITE
x
:ZX_RIGHT_EXECUTE
m
:ZX_RIGHT_MAP
d
:ZX_RIGHT_DUPLICATE
t
:ZX_RIGHT_TRANSFER
- 注意:非帳號代碼項目在這一欄中會有一個「-」。
koid
:VMO 的 koid (如有)。否則傳回 0。沒有 koid 的 VMO 是由核心建立,從未有使用者空間控制代碼。parent
:VMO 父項的 koid (如果是子項)。#chld
:VMO 的有效子項數量。#map
:VMO 目前對應至 VMAR 的次數。#shr
:對應 (共用) VMO 的程序數量。size
:VMO 目前的大小,以位元組為單位。alloc
:分配給 VMO 的實體記憶體數量,以位元組為單位。- 注意:如果此欄包含
phys
值,表示 VMO 會指向原始實體位址範圍,例如記憶體對應裝置。phys
VMO 不會耗用 RAM。
- 注意:如果此欄包含
name
:VMO 的名稱;如果名稱空白,則為-
。
與 ps
的關聯:每個 VMO 都有其對應部分 (因為可以對應全部或任何 VMO 頁面):
PRIVATE = #shr == 1 ? alloc : 0
SHARED = #shr > 1 ? alloc : 0
PSS = PRIVATE + (SHARED / #shr)
您也可以使用 zxdb 中的
handle
指令顯示 VMO 資訊。
傾印「已隱藏」(未對應和核心) VMO
k zx vmos hidden
與 vmos <pid>
類似,但會傾印系統中未對應至任何程序的所有 VMO:
- 使用者空間有控制代碼但不會對應的 VMO
- 只對應到核心空間的 VMO
- 僅限核心且未對應的 VMO,沒有帳號代碼
koid
值為 0 表示只有核心有該 VMO 的參照。
如果 #map
值為 0,表示 VMO 未對應到任何位址空間。
另請參閱:k zx vmos all
,這會傾印系統中的所有 VMO。注意:由於核心控制台的緩衝區限制,此輸出內容往往會遭到截斷,因此通常最好將 k zx vmos hidden
輸出內容與每個使用者程序的 vmaps
傾印結合。
限制
ps
和 vmaps
目前未將下列項目納入考量:
- 未對應的 VMO 或 VMO 子範圍。舉例來說,您可以建立 VMO,將 1G 資料寫入其中,然後不會顯示在這裡。
任何程序傾印工具都無法說明以下事項:
對應的頁面。如果您使用相同的 VMO 範圍建立多個對應關係,系統會將 VMO 的任何修訂頁面計為對應的頁面對應次數。這可能位於相同程序內,也可能在相同程序之間 (如果這些程序共用 VMO)。
請注意,「相對應的網頁」包括寫入時複製。
對程序分配的資源造成核心記憶體負擔。舉例來說,一項程序可能會開啟一百萬個處理點,而這些程序會耗用核心記憶體。
您可以利用
k zx ps
指令查看程序處理的使用量;執行k zx ps help
以取得資料欄的說明。複製時複製 (COW) 的 VMO。對於對應本機副本的程序,乾淨 (非骯髒、未複製) 頁面不會計入「共用」中,而相同的頁面可能會錯誤計入對應父項 (複製) VMO 的程序的「私人」。
TODO(dbort):修正此問題;工具是在 COW 副本存在前編寫。
核心記憶體
傾印系統記憶體空間和核心堆積用量
執行 kstats -m
會持續傾印實體記憶體用量和可用性的相關資訊。
$ kstats -m
--- 2017-06-07T05:51:08.021Z ---
mem total free VMOs kheap kfree wired mmu ipc other
2048M 1686.4M 317.8M 5.1M 0.9M 17.8M 20.0M 0.1M 0.0M
--- 2017-06-07T05:51:09.021Z ---
...
欄位:
-t
選項會在收集統計資料時,顯示時間戳記2017-06-07T05:51:08.021Z
,以 ISO 8601 字串表示。total
:系統可用的實體記憶體總量。free
:未分配的記憶體數量。VMOs
:承諾分配給 VMO 的記憶體量 (核心和使用者)。所有使用者空間記憶體的超集合。不包含屬於wired
的特定 VMO。kheap
:標示為已分配的核心堆積記憶體數量。kfree
:標示為免費的核心堆積記憶體數量。wired
:基於這個結構中其他欄位未涵蓋的原因,預留的記憶體容量,並對應至核心的數量。通常用於唯讀資料,例如 RAM 磁碟和核心映像檔,以及用於早期啟動的動態記憶體。mmu
:用於架構專屬 MMU 中繼資料 (例如頁面資料表) 的記憶體量。ipc
:用於處理序間通訊的記憶體量。other
:其他優先順序為other
。
傾印核心位址空間
k zx asd kernel
傾印核心的 VMAR/對應/VMO 階層,類似於使用者程序的 vmaps
工具。
$ k zx asd kernel
as 0xffffffff80252b20 [0xffffff8000000000 0xffffffffffffffff] sz 0x8000000000 fl 0x1 ref 71 'kernel'
vmar 0xffffffff802529a0 [0xffffff8000000000 0xffffffffffffffff] sz 0x8000000000 ref 1 'root'
map 0xffffff80015f89a0 [0xffffff8000000000 0xffffff8fffffffff] sz 0x1000000000 mmufl 0x18 vmo 0xffffff80015f8890/k0 off 0 p ages 0 ref 1 ''
vmo 0xffffff80015f8890/k0 size 0 pages 0 ref 1 parent k0
map 0xffffff80015f8b30 [0xffffff9000000000 0xffffff9000000fff] sz 0x1000 mmufl 0x18 vmo 0xffffff80015f8a40/k0 off 0 pages 0 ref 1 ''
object 0xffffff80015f8a40 base 0x7ffe2000 size 0x1000 ref 1
map 0xffffff80015f8cc0 [0xffffff9000001000 0xffffff9000001fff] sz 0x1000 mmufl 0x1a vmo 0xffffff80015f8bd0/k0 off 0 pages 0 ref 1 ''
object 0xffffff80015f8bd0 base 0xfed00000 size 0x1000 ref 1
...