/proc 檔案系統¶
/proc/sys |
Terrehon Bowden <terrehon@pacbell.net>, Bodo Bauer <bb@ricochet.net> |
1999 年 10 月 7 日 |
2.4.x 更新 |
Jorge Nerin <comandante@zaralinux.com> |
2000 年 11 月 14 日 |
移動 /proc/sys |
Shen Feng <shen@cn.fujitsu.com> |
2009 年 4 月 1 日 |
修復/更新 第 1.1 部分 |
Stefani Seibold <stefani@seibold.net> |
2009 年 6 月 9 日 |
前言¶
0.1 引言/鳴謝¶
本文件是即將釋出(或者我們希望如此)的關於 SuSE Linux 發行版的書籍的一部分。由於 /proc 檔案系統沒有完整的文件,並且我們使用了許多免費提供的資源來編寫這些章節,因此將這項工作回饋給 Linux 社群似乎是公平的。這項工作基於 2.2.* 核心版本和即將到來的 2.4.*。恐怕它還遠未完成,但我們希望它會有用。據我們所知,這是第一份關於 /proc 檔案系統的“all-in-one”文件。它專注於 Intel x86 硬體,因此如果您正在尋找 PPC、ARM、SPARC、AXP 等功能,您可能找不到您要找的東西。它也只涵蓋 IPv4 網路,不包括 IPv6 或其他協議 - 抱歉。但是歡迎新增和補丁,如果您將它們郵寄給 Bodo,它們將被新增到本文件中。
我們要感謝 Alan Cox、Rik van Riel 和 Alexey Kuznetsov 以及許多其他人幫助編寫本文件。我們還要特別感謝 Andi Kleen 的文件,我們在建立本文件時嚴重依賴這些文件,以及他提供的其他資訊。感謝所有為 Linux 核心貢獻原始碼或文件並幫助創建出色軟體的人…… :)
如果您有任何意見、更正或補充,請隨時透過 bb@ricochet.net 聯絡 Bodo Bauer。我們很樂意將它們新增到本文件中。
本文件的最新版本可在網上找到:https://kernel.linux.club.tw/doc/html/latest/filesystems/proc.html
如果上述方向對您不起作用,您可以嘗試核心郵件列表 linux-kernel@vger.kernel.org 和/或嘗試透過 comandante@zaralinux.com 與我聯絡。
0.2 法律宣告¶
我們不保證本文件的正確性,如果您因為不正確的文件而搞砸了您的系統而向我們抱怨,我們不會承擔責任……
第 1 章:收集系統資訊¶
本章內容¶
調查偽檔案系統 /proc 的屬性及其提供有關執行中的 Linux 系統的資訊的能力
檢查 /proc 的結構
揭示有關核心和系統上執行的程序的各種資訊
proc 檔案系統充當核心中內部資料結構的介面。它可用於獲取有關係統的資訊並在執行時更改某些核心引數 (sysctl)。
首先,我們將看看 /proc 的只讀部分。在第 2 章中,我們將向您展示如何使用 /proc/sys 更改設定。
1.1 程序特定的子目錄¶
/proc 目錄(除其他外)包含系統上執行的每個程序的一個子目錄,該子目錄以程序 ID (PID) 命名。
連結“self”指向讀取檔案系統的程序。每個程序子目錄都有表 1-1 中列出的條目。
程序可以從 /proc/PID/* 讀取自己的資訊,而無需額外的許可權。讀取其他程序的 /proc/PID/* 資訊時,讀取程序需要具有 CAP_SYS_PTRACE 能力和 PTRACE_MODE_READ 訪問許可權,或者具有 CAP_PERFMON 能力。這適用於所有隻讀資訊,如 maps、environ、pagemap 等。唯一的例外是 mem 檔案,由於其讀寫性質,需要 CAP_SYS_PTRACE 能力和更高的 PTRACE_MODE_ATTACH 許可權;CAP_PERFMON 能力不授予對其他程序的 /proc/PID/mem 的訪問許可權。
請注意,開啟 /proc/<pid> 或其包含的任何檔案或子目錄的檔案描述符不會阻止 <pid> 在 <pid> 退出的情況下被其他程序重用。對與已死程序對應的開啟 /proc/<pid> 檔案描述符的操作永遠不會對核心可能(透過偶然)也分配了程序 ID <pid> 的任何新程序起作用。相反,對這些 FD 的操作通常會失敗,並出現 ESRCH。
檔案 |
內容 |
|---|---|
clear_refs |
清除 smaps 輸出中顯示 的頁面引用位 |
cmdline |
命令列引數 |
cpu |
當前和上次執行的 cpu (2.4)(smp) |
cwd |
連結到當前工作目錄 |
environ |
環境變數的值 |
exe |
連結到此程序的可執行檔案 |
fd |
目錄,其中包含所有檔案描述符 |
maps |
到可執行檔案和庫檔案的記憶體對映 (2.4) |
mem |
此程序持有的記憶體 |
root |
連結到此程序的根目錄 |
stat |
程序狀態 |
statm |
程序記憶體狀態資訊 |
status |
以人類可讀形式顯示的程序狀態 |
wchan |
存在 CONFIG_KALLSYMS=y 時:它顯示任務阻塞的核心函式符號 - 如果未阻塞,則顯示“0”。 |
pagemap |
頁表 |
stack |
報告完整堆疊跟蹤,透過 CONFIG_STACKTRACE 啟用 |
smaps |
基於 maps 的擴充套件,顯示每個對映的記憶體消耗以及與之關聯的標誌 |
smaps_rollup |
程序所有對映的累積 smaps 統計資訊。這可以從 smaps 派生,但速度更快、更方便 |
numa_maps |
基於 maps 的擴充套件,顯示記憶體區域性性和繫結策略以及每個對映的記憶體使用情況(以頁為單位)。 |
例如,要獲取程序的狀態資訊,您所要做的就是讀取檔案 /proc/PID/status
>cat /proc/self/status
Name: cat
State: R (running)
Tgid: 5452
Pid: 5452
PPid: 743
TracerPid: 0 (2.4)
Uid: 501 501 501 501
Gid: 100 100 100 100
FDSize: 256
Groups: 100 14 16
Kthread: 0
VmPeak: 5004 kB
VmSize: 5004 kB
VmLck: 0 kB
VmHWM: 476 kB
VmRSS: 476 kB
RssAnon: 352 kB
RssFile: 120 kB
RssShmem: 4 kB
VmData: 156 kB
VmStk: 88 kB
VmExe: 68 kB
VmLib: 1412 kB
VmPTE: 20 kb
VmSwap: 0 kB
HugetlbPages: 0 kB
CoreDumping: 0
THP_enabled: 1
Threads: 1
SigQ: 0/28578
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000000
SigCgt: 0000000000000000
CapInh: 00000000fffffeff
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: ffffffffffffffff
CapAmb: 0000000000000000
NoNewPrivs: 0
Seccomp: 0
Speculation_Store_Bypass: thread vulnerable
SpeculationIndirectBranch: conditional enabled
voluntary_ctxt_switches: 0
nonvoluntary_ctxt_switches: 1
這會向您顯示幾乎與您使用 ps 命令檢視時相同的資訊。實際上,ps 使用 proc 檔案系統來獲取其資訊。但是,透過讀取檔案 /proc/PID/status,您可以獲得程序的更詳細檢視。它的欄位在表 1-2 中描述。
statm 檔案包含有關程序記憶體使用情況的更多詳細資訊。它的七個欄位在表 1-3 中解釋。stat 檔案包含有關程序本身的詳細資訊。它的欄位在表 1-4 中解釋。
(對於 SMP CONFIG 使用者)
為了使記帳可擴充套件,RSS 相關資訊以非同步方式處理,並且該值可能不是很精確。要檢視某個時刻的精確快照,您可以檢視 /proc/<pid>/smaps 檔案並掃描頁表。它很慢,但非常精確。
欄位 |
內容 |
|---|---|
名稱 |
可執行檔案的檔名 |
Umask |
檔案模式建立掩碼 |
State |
狀態(R 是執行,S 是睡眠,D 是在不可中斷的等待中睡眠,Z 是殭屍,T 是被跟蹤或停止) |
Tgid |
執行緒組 ID |
Ngid |
NUMA 組 ID(如果沒有,則為 0) |
Pid |
程序 ID |
PPid |
父程序的程序 ID |
TracerPid |
跟蹤此程序的程序的 PID(如果不是,或者跟蹤器在當前 pid 名稱空間之外,則為 0) |
Uid |
實際、有效、儲存的集合和檔案系統 UID |
Gid |
實際、有效、儲存的集合和檔案系統 GID |
FDSize |
當前分配的檔案描述符槽數 |
Groups |
補充組列表 |
NStgid |
後代名稱空間執行緒組 ID 層次結構 |
NSpid |
後代名稱空間程序 ID 層次結構 |
NSpgid |
後代名稱空間程序組 ID 層次結構 |
NSsid |
後代名稱空間會話 ID 層次結構 |
Kthread |
核心執行緒標誌,1 表示是,0 表示否 |
VmPeak |
峰值虛擬記憶體大小 |
VmSize |
總程式大小 |
VmLck |
鎖定的記憶體大小 |
VmPin |
固定的記憶體大小 |
VmHWM |
峰值常駐集大小(“最高水位線”) |
VmRSS |
記憶體部分的大小。它包含以下三個部分(VmRSS = RssAnon + RssFile + RssShmem) |
RssAnon |
常駐匿名記憶體的大小 |
RssFile |
常駐檔案對映的大小 |
RssShmem |
常駐 shmem 記憶體的大小(包括 SysV shm、tmpfs 對映和共享匿名對映) |
VmData |
私有資料段的大小 |
VmStk |
堆疊段的大小 |
VmExe |
文字段的大小 |
VmLib |
共享庫程式碼的大小 |
VmPTE |
頁表條目的大小 |
VmSwap |
匿名私有資料使用的交換空間量(不包括 shmem 交換空間使用量) |
HugetlbPages |
hugetlb 記憶體部分的大小 |
CoreDumping |
程序的記憶體當前正在轉儲(終止程序可能會導致核心損壞) |
THP_enabled |
程序允許使用 THP(當在程序上設定 PR_SET_THP_DISABLE 時返回 0 |
Threads |
執行緒數 |
SigQ |
排隊的訊號數/佇列的最大數 |
SigPnd |
執行緒的掛起訊號點陣圖 |
ShdPnd |
程序的共享掛起訊號點陣圖 |
SigBlk |
阻止的訊號點陣圖 |
SigIgn |
忽略的訊號點陣圖 |
SigCgt |
捕獲的訊號點陣圖 |
CapInh |
可繼承能力的點陣圖 |
CapPrm |
允許的能力的點陣圖 |
CapEff |
有效能力的點陣圖 |
CapBnd |
能力邊界集點陣圖 |
CapAmb |
環境能力點陣圖 |
NoNewPrivs |
no_new_privs,如 prctl(PR_GET_NO_NEW_PRIV, ...) |
Seccomp |
seccomp 模式,如 prctl(PR_GET_SECCOMP, ...) |
Speculation_Store_Bypass |
推測儲存旁路緩解狀態 |
SpeculationIndirectBranch |
間接分支推測模式 |
Cpus_allowed |
此程序可以在其上執行的 CPU 掩碼 |
Cpus_allowed_list |
與上一個相同,但以“列表格式”顯示 |
Mems_allowed |
允許此程序使用的記憶體節點掩碼 |
Mems_allowed_list |
與上一個相同,但以“列表格式”顯示 |
voluntary_ctxt_switches |
自願上下文切換的次數 |
nonvoluntary_ctxt_switches |
非自願上下文切換的次數 |
欄位 |
內容 |
|
|---|---|---|
size |
總程式大小(頁) |
(與 status 中的 VmSize 相同) |
resident |
記憶體部分的大小(頁) |
(與 status 中的 VmRSS 相同) |
shared |
共享的頁數 |
(即由檔案支援,與 status 中的 RssFile+RssShmem 相同) |
trs |
“程式碼”的頁數 |
(不包括 libs;已損壞,包括資料段) |
lrs |
庫頁數 |
(在 2.6 上始終為 0) |
drs |
資料/堆疊的頁數 |
(包括 libs;已損壞,包括庫文字) |
dt |
髒頁數 |
(在 2.6 上始終為 0) |
欄位 |
內容 |
|---|---|
pid |
程序 ID |
tcomm |
可執行檔案的檔名 |
state |
狀態(R 是執行,S 是睡眠,D 是在不可中斷的等待中睡眠,Z 是殭屍,T 是被跟蹤或停止) |
ppid |
父程序的程序 ID |
pgrp |
程序的 pgrp |
sid |
會話 ID |
tty_nr |
程序使用的 tty |
tty_pgrp |
tty 的 pgrp |
flags |
任務標誌 |
min_flt |
次要錯誤的數量 |
cmin_flt |
帶有子程序的次要錯誤的數量 |
maj_flt |
主要錯誤的數量 |
cmaj_flt |
帶有子程序的主要錯誤的數量 |
utime |
使用者模式節拍數 |
stime |
核心模式節拍數 |
cutime |
帶有子程序的使用者模式節拍數 |
cstime |
帶有子程序的核心模式節拍數 |
priority |
優先順序 |
nice |
nice 級別 |
num_threads |
執行緒數 |
it_real_value |
(已過時,始終為 0) |
start_time |
系統啟動後進程啟動的時間 |
vsize |
虛擬記憶體大小 |
rss |
常駐集記憶體大小 |
rsslim |
rss 的當前位元組限制 |
start_code |
程式文字可以在其上方執行的地址 |
end_code |
程式文字可以在其下方執行的地址 |
start_stack |
主程序堆疊的起始地址 |
esp |
ESP 的當前值 |
eip |
EIP 的當前值 |
pending |
掛起訊號的點陣圖 |
blocked |
阻止的訊號點陣圖 |
sigign |
忽略的訊號點陣圖 |
sigcatch |
捕獲的訊號點陣圖 |
0 |
(佔位符,曾經是 wchan 地址,請改用 /proc/PID/wchan) |
0 |
(佔位符) |
0 |
(佔位符) |
exit_signal |
退出時要傳送到父執行緒的訊號 |
task_cpu |
任務計劃在其上執行的 CPU |
rt_priority |
即時優先順序 |
policy |
排程策略 (man sched_setscheduler) |
blkio_ticks |
等待塊 IO 的時間 |
gtime |
任務的客戶時間(以節拍為單位) |
cgtime |
任務子程序的客戶時間(以節拍為單位) |
start_data |
程式 data+bss 放置在其上方的地址 |
end_data |
程式 data+bss 放置在其下方的地址 |
start_brk |
程式堆可以透過 brk() 擴充套件的地址 |
arg_start |
程式命令列放置在其上方的地址 |
arg_end |
程式命令列放置在其下方的地址 |
env_start |
程式環境放置在其上方的地址 |
env_end |
程式環境放置在其下方的地址 |
exit_code |
waitpid 系統呼叫報告的執行緒的 exit_code 形式 |
/proc/PID/maps 檔案包含當前對映的記憶體區域及其訪問許可權。
格式為
address perms offset dev inode pathname
08048000-08049000 r-xp 00000000 03:00 8312 /opt/test
08049000-0804a000 rw-p 00001000 03:00 8312 /opt/test
0804a000-0806b000 rw-p 00000000 00:00 0 [heap]
a7cb1000-a7cb2000 ---p 00000000 00:00 0
a7cb2000-a7eb2000 rw-p 00000000 00:00 0
a7eb2000-a7eb3000 ---p 00000000 00:00 0
a7eb3000-a7ed5000 rw-p 00000000 00:00 0
a7ed5000-a8008000 r-xp 00000000 03:00 4222 /lib/libc.so.6
a8008000-a800a000 r--p 00133000 03:00 4222 /lib/libc.so.6
a800a000-a800b000 rw-p 00135000 03:00 4222 /lib/libc.so.6
a800b000-a800e000 rw-p 00000000 00:00 0
a800e000-a8022000 r-xp 00000000 03:00 14462 /lib/libpthread.so.0
a8022000-a8023000 r--p 00013000 03:00 14462 /lib/libpthread.so.0
a8023000-a8024000 rw-p 00014000 03:00 14462 /lib/libpthread.so.0
a8024000-a8027000 rw-p 00000000 00:00 0
a8027000-a8043000 r-xp 00000000 03:00 8317 /lib/ld-linux.so.2
a8043000-a8044000 r--p 0001b000 03:00 8317 /lib/ld-linux.so.2
a8044000-a8045000 rw-p 0001c000 03:00 8317 /lib/ld-linux.so.2
aff35000-aff4a000 rw-p 00000000 00:00 0 [stack]
ffffe000-fffff000 r-xp 00000000 00:00 0 [vdso]
其中“address”是它佔用的程序中的地址空間,“perms”是一組許可權
r = read
w = write
x = execute
s = shared
p = private (copy on write)
“offset”是對映中的偏移量,“dev”是裝置(major:minor),“inode”是該裝置上的 inode。0 表示沒有 inode 與記憶體區域關聯,BSS(未初始化的資料)就是這種情況。“pathname”顯示與此對映關聯的檔案的名稱。如果對映未與檔案關聯
[heap]
程式的堆
[stack]
主程序的堆疊
[vdso]
“虛擬動態共享物件”,核心系統呼叫處理程式
[anon:<name>]
已被使用者空間命名的私有匿名對映
[anon_shmem:<name>]
已被使用者空間命名的匿名共享記憶體對映
或者,如果為空,則對映是匿名的。
從 6.11 核心開始,/proc/PID/maps 提供了一個替代的基於 ioctl() 的 API,該 API 能夠靈活高效地查詢和過濾單個 VMA。struct procmap_query,在 linux/fs.h UAPI 標頭中定義,用作 PROCMAP_QUERY ioctl() 命令的輸入/輸出引數。有關查詢語義、支援的標誌、返回的資料以及常規 API 用法資訊的詳細資訊,請參見 linus/fs.h UAPI 標頭中的註釋。
/proc/PID/smaps 是基於 maps 的擴充套件,顯示了程序的每個對映的記憶體消耗。對於每個對映(也稱為虛擬記憶體區域或 VMA),都有一系列行,例如以下內容
08048000-080bc000 r-xp 00000000 03:02 13130 /bin/bash
Size: 1084 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Rss: 892 kB
Pss: 374 kB
Pss_Dirty: 0 kB
Shared_Clean: 892 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 892 kB
Anonymous: 0 kB
KSM: 0 kB
LazyFree: 0 kB
AnonHugePages: 0 kB
ShmemPmdMapped: 0 kB
Shared_Hugetlb: 0 kB
Private_Hugetlb: 0 kB
Swap: 0 kB
SwapPss: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
THPeligible: 0
VmFlags: rd ex mr mw me dw
這些行的第一行顯示與 /proc/PID/maps 中顯示的對映相同的資訊。以下行顯示對映的大小(大小);在支援 VMA 時分配的每個頁面的大小(KernelPageSize),通常與頁表條目中的大小相同;MMU 在支援 VMA 時使用的頁面大小(在大多數情況下,與 KernelPageSize 相同);當前駐留在 RAM 中的對映量 (RSS);程序在此對映中的比例份額 (PSS);以及對映中乾淨和髒的共享頁面和私有頁面的數量。
程序的“比例集大小”(PSS) 是其在記憶體中擁有的頁面計數,其中每個頁面都除以共享它的程序數。因此,如果一個程序擁有 1000 個頁面,並且與另一個程序共享 1000 個頁面,則其 PSS 將為 1500。“Pss_Dirty”是 PSS 中由髒頁面組成的部分。(不包括“Pss_Clean”,但可以透過從“Pss”中減去“Pss_Dirty”來計算。)
傳統上,如果一個頁面被對映一次,則將其計為“私有”頁面;當頁面被多次對映時,則將其計為“共享”頁面,即使在同一程序中多次對映也是如此。請注意,此記帳獨立於 MAP_SHARED。
在某些核心配置中,較大分配(例如,THP)的一部分的頁面的語義可能有所不同:如果屬於相應較大分配的所有頁面確定在同一程序中對映(即使該頁面在該程序中對映多次),則該頁面將計為“私有”頁面。如果較大分配的任何頁面可能在不同的程序中對映,則該頁面將計為“共享”頁面。在某些情況下,即使較大分配不再是這種情況,也可能將其視為“可能被多個程序對映”。
某些核心配置不跟蹤較大分配的一部分的頁面對映的精確次數。在這種情況下,在計算 PSS 時,此較大分配中每個頁面的平均對映數可以用作頁面對映數的近似值。在這種情況下,PSS 計算將是不精確的。
“Referenced”指示當前標記為引用或訪問的記憶體量。
“Anonymous”顯示不屬於任何檔案的記憶體量。即使與檔案關聯的對映也可能包含匿名頁面:當 MAP_PRIVATE 和一個頁面被修改時,檔案頁面將被私有匿名副本替換。
“KSM”報告有多少頁面是 KSM 頁面。請注意,不包括 KSM 放置的零頁面,僅包括實際 KSM 頁面。
“LazyFree”顯示 madvise(MADV_FREE) 標記的記憶體量。該記憶體不會立即透過 madvise() 釋放。如果在記憶體壓力下記憶體是乾淨的,則會釋放該記憶體。請注意,由於當前實現中使用的最佳化,列印的值可能低於實際值。如果這是不可取的,請提交錯誤報告。
“AnonHugePages”顯示由透明巨頁支援的記憶體量。
“ShmemPmdMapped”顯示由巨頁支援的共享 (shmem/tmpfs) 記憶體量。
“Shared_Hugetlb”和“Private_Hugetlb”顯示由 hugetlbfs 頁面支援的記憶體量,由於歷史原因,該記憶體未計入“RSS”或“PSS”欄位中。並且這些不包括在 {Shared,Private}_{Clean,Dirty} 欄位中。
“Swap”顯示了多少可以成為匿名記憶體也被使用,但已在交換空間中。
對於 shmem 對映,“Swap”還包括 shmem 物件底層交換空間上對映(並且未被寫時複製替換)部分的大小。“SwapPss”顯示此對映的比例交換空間份額。與“Swap”不同,這不考慮底層 shmem 物件的交換出頁面。“Locked”指示對映是否鎖定在記憶體中。
“THPeligible”指示對映是否符合分配任何當前啟用的自然對齊 THP 頁面的大小。如果為真,則為 1;否則為 0。
“VmFlags”欄位值得單獨描述。此成員以雙字母編碼方式表示與特定虛擬記憶體區域關聯的核心標誌。程式碼如下
rd
可讀
wr
可寫
ex
可執行
sh
shared
mr
可能讀取
mw
可能寫入
me
可能執行
ms
可能共享
gd
堆疊段向下增長
pf
純 PFN 範圍
lo
頁面鎖定在記憶體中
io
記憶體對映 I/O 區域
sr
提供順序讀取建議
rr
提供隨機讀取建議
dc
不在 fork 時複製區域
de
不在重新對映時擴充套件區域
ac
該區域是可記帳的
nr
未為此區域保留交換空間
ht
該區域使用巨型 tlb 頁面
sf
同步頁面錯誤
ar
特定於架構的標誌
wf
在 fork 時擦除
dd
不將該區域包含到核心轉儲中
sd
軟髒標誌
mm
混合對映區域
hg
巨頁建議標誌
nh
無巨頁建議標誌
mg
可合併建議標誌
bt
arm64 BTI 受保護頁面
mt
已啟用 arm64 MTE 分配標記
um
userfaultfd 缺少跟蹤
uw
userfaultfd wr-protect 跟蹤
ui
userfaultfd 次要錯誤
ss
陰影/受保護的控制堆疊頁面
sl
密封
lf
在錯誤頁面上鎖定
dp
始終可延遲釋放的對映
請注意,不能保證每個標誌和關聯的助記符都會出現在所有以後的核心版本中。事情會發生變化,標誌可能會消失,或者相反——會新增新的標誌。將來對其含義的解釋也可能會發生變化。因此,這些標誌的每個使用者都必須遵循每個特定的核心版本,以瞭解其確切的語義。
僅當啟用 CONFIG_MMU 核心配置選項時,此檔案才存在。
注意:讀取 /proc/PID/maps 或 /proc/PID/smaps 本質上是競爭的(只有在單個讀取呼叫中才能實現一致的輸出)。
當在修改記憶體對映時對這些檔案進行部分讀取時,通常會表現出這種情況。儘管存在競爭,但我們確實提供了以下保證
對映的地址永遠不會向後移動,這意味著沒有兩個區域會重疊。
如果在 smaps/maps 遍歷的整個生命週期中,給定的 vaddr 上存在某些內容,則會為其提供一些輸出。
/proc/PID/smaps_rollup 檔案包含與 /proc/PID/smaps 相同的欄位,但其值是程序所有對映的相應值的總和。此外,它還包含以下欄位
Pss_Anon
Pss_File
Pss_Shmem
它們表示匿名頁面、檔案頁面和 shmem 頁面的比例份額,如上文針對 smaps 所述。這些欄位在 smaps 中被省略,因為每個對映都標識了它包含的所有頁面的型別(匿名頁面、檔案頁面或 shmem 頁面)。因此,smaps_rollup 中的所有資訊都可以從 smaps 派生,但成本要高得多。
/proc/PID/clear_refs 用於重置與程序關聯的物理頁面和虛擬頁面上的 PG_Referenced 和 ACCESSED/YOUNG 位,以及 pte 上的軟髒位(有關詳細資訊,請參見 Soft-Dirty PTEs)。要清除與程序關聯的所有頁面的位
> echo 1 > /proc/PID/clear_refs
要清除與程序關聯的匿名頁面的位
> echo 2 > /proc/PID/clear_refs
要清除與程序關聯的檔案對映頁面的位
> echo 3 > /proc/PID/clear_refs
要清除軟髒位
> echo 4 > /proc/PID/clear_refs
要將峰值常駐集大小(“最高水位線”)重置為程序的當前值
> echo 5 > /proc/PID/clear_refs
寫入 /proc/PID/clear_refs 的任何其他值都不會產生任何影響。
/proc/pid/pagemap 提供 PFN,可用於使用 /proc/kpageflags 查詢頁面標誌,並使用 /proc/kpagecount 查詢頁面對映的次數。有關詳細說明,請參見 Examining Process Page Tables。
/proc/pid/numa_maps 是基於 maps 的擴充套件,顯示了記憶體區域性性和繫結策略,以及每個對映的記憶體使用情況(以頁為單位)。輸出遵循一種通用格式,其中對映詳細資訊被空格分隔地彙總,每個對映一行
address policy mapping details
00400000 default file=/usr/local/bin/app mapped=1 active=0 N3=1 kernelpagesize_kB=4
00600000 default file=/usr/local/bin/app anon=1 dirty=1 N3=1 kernelpagesize_kB=4
3206000000 default file=/lib64/ld-2.12.so mapped=26 mapmax=6 N0=24 N3=2 kernelpagesize_kB=4
320621f000 default file=/lib64/ld-2.12.so anon=1 dirty=1 N3=1 kernelpagesize_kB=4
3206220000 default file=/lib64/ld-2.12.so anon=1 dirty=1 N3=1 kernelpagesize_kB=4
3206221000 default anon=1 dirty=1 N3=1 kernelpagesize_kB=4
3206800000 default file=/lib64/libc-2.12.so mapped=59 mapmax=21 active=55 N0=41 N3=18 kernelpagesize_kB=4
320698b000 default file=/lib64/libc-2.12.so
3206b8a000 default file=/lib64/libc-2.12.so anon=2 dirty=2 N3=2 kernelpagesize_kB=4
3206b8e000 default file=/lib64/libc-2.12.so anon=1 dirty=1 N3=1 kernelpagesize_kB=4
3206b8f000 default anon=3 dirty=3 active=1 N3=3 kernelpagesize_kB=4
7f4dc10a2000 default anon=3 dirty=3 N3=3 kernelpagesize_kB=4
7f4dc10b4000 default anon=2 dirty=2 active=1 N3=2 kernelpagesize_kB=4
7f4dc1200000 default file=/anon_hugepage\040(deleted) huge anon=1 dirty=1 N3=1 kernelpagesize_kB=2048
7fff335f0000 default stack anon=3 dirty=3 N3=3 kernelpagesize_kB=4
7fff3369d000 default mapped=1 mapmax=35 active=0 N3=1 kernelpagesize_kB=4
其中
“address”是對映的起始地址;
“policy”報告為對映設定的 NUMA 記憶體策略(請參見 NUMA 記憶體策略);
“mapping details”彙總了對映資料,例如對映型別、頁面使用計數器、節點區域性性頁面計數器(N0 == node0,N1 == node1,...)以及支援對映的核心頁面大小(以 KB 為單位)。
請注意,某些核心配置不跟蹤較大分配(例如,THP)的一部分頁面對映的精確次數。在這些配置中,“mapmax”可能對應於此類較大分配中每個頁面的平均對映數。
1.2 核心資料¶
與程序條目類似,核心資料檔案提供有關執行核心的資訊。用於獲取此資訊的檔案包含在 /proc 中,並在表 1-5 中列出。並非所有檔案都將存在於您的系統中。這取決於核心配置和已載入的模組,哪些檔案存在,哪些檔案缺失。
檔案 |
內容 |
|---|---|
allocinfo |
記憶體分配分析資訊 |
apm |
高階電源管理資訊 |
bootconfig |
從引導配置獲得的核心命令列,以及,如果有來自引導載入程式的核心引數,則有一行“# 來自引導載入程式的引數:”,後跟一行包含以“# ”為字首的那些引數。(5.5) |
buddyinfo |
核心記憶體分配器資訊(請參見文字)(2.5) |
bus |
包含匯流排特定資訊的目錄 |
cmdline |
核心命令列,包括來自引導載入程式和嵌入在核心映象中的 |
cpuinfo |
CPU 相關資訊 |
devices |
可用裝置(塊裝置和字元裝置) |
dma |
已使用的 DMA 通道 |
filesystems |
支援的檔案系統 |
driver |
各種驅動程式在此分組,目前是 rtc (2.4) |
execdomains |
執行域,與安全性相關 (2.4) |
fb |
幀緩衝區裝置 (2.4) |
fs |
檔案系統引數,目前是 nfs/exports (2.4) |
ide |
包含 IDE 子系統資訊的目錄 |
interrupts |
中斷使用情況 |
iomem |
記憶體對映 (2.4) |
ioports |
I/O 埠使用情況 |
irq |
IRQ 到 CPU 親和性的掩碼 (2.4)(smp?) |
isapnp |
ISA PnP (即插即用) 資訊 (2.4) |
kcore |
核心核心映象(可以是 ELF 或 A.OUT(在 2.4 中已棄用)) |
kmsg |
核心訊息 |
ksyms |
核心符號表 |
loadavg |
|
locks |
核心鎖 |
meminfo |
記憶體資訊 |
misc |
雜項 |
modules |
已載入模組列表 |
mounts |
已掛載的檔案系統 |
net |
網路資訊(見正文) |
pagetypeinfo |
額外的頁面分配器資訊(見正文)(2.5) |
partitions |
系統已知的分割槽表 |
pci |
PCI 匯流排的已棄用資訊(新方法 -> /proc/bus/pci/,由 lspci 解耦 (2.4)) |
rtc |
即時時鐘 |
scsi |
SCSI 資訊(見正文) |
slabinfo |
Slab 池資訊 |
softirqs |
軟中斷使用情況 |
stat |
總體統計 |
swaps |
交換空間利用率 |
sys |
參見第 2 章 |
sysvipc |
SysVIPC 資源資訊(msg、sem、shm)(2.4) |
tty |
tty 驅動程式資訊 |
uptime |
自啟動以來的掛鐘時間,所有 CPU 的總空閒時間 |
version |
核心版本 |
video |
影片資源的 bttv 資訊 (2.4) |
vmallocinfo |
顯示 vmalloced 區域 |
例如,您可以透過檢視 /proc/interrupts 檔案來檢查當前正在使用的中斷以及它們的用途
> cat /proc/interrupts
CPU0
0: 8728810 XT-PIC timer
1: 895 XT-PIC keyboard
2: 0 XT-PIC cascade
3: 531695 XT-PIC aha152x
4: 2014133 XT-PIC serial
5: 44401 XT-PIC pcnet_cs
8: 2 XT-PIC rtc
11: 8 XT-PIC i82365
12: 182918 XT-PIC PS/2 Mouse
13: 1 XT-PIC fpu
14: 1232265 XT-PIC ide0
15: 7 XT-PIC ide1
NMI: 0
在 2.4.* 中,該檔案中添加了幾行 LOC & ERR(這次是 SMP 機器的輸出)
> cat /proc/interrupts
CPU0 CPU1
0: 1243498 1214548 IO-APIC-edge timer
1: 8949 8958 IO-APIC-edge keyboard
2: 0 0 XT-PIC cascade
5: 11286 10161 IO-APIC-edge soundblaster
8: 1 0 IO-APIC-edge rtc
9: 27422 27407 IO-APIC-edge 3c503
12: 113645 113873 IO-APIC-edge PS/2 Mouse
13: 0 0 XT-PIC fpu
14: 22491 24012 IO-APIC-edge ide0
15: 2183 2415 IO-APIC-edge ide1
17: 30564 30414 IO-APIC-level eth0
18: 177 164 IO-APIC-level bttv
NMI: 2457961 2457959
LOC: 2457882 2457881
ERR: 2155
在這種情況下,NMI 遞增,因為每個定時器中斷都會生成一個 NMI(不可遮蔽中斷),NMI Watchdog 使用它來檢測死鎖。
LOC 是每個 CPU 內部 APIC 的本地中斷計數器。
如果在 IO-APIC 匯流排(連線 SMP 系統中 CPU 的匯流排)中出現錯誤,ERR 將遞增。這意味著檢測到了錯誤,IO-APIC 會自動重試傳輸,因此這應該不是大問題,但您應該閱讀 SMP-FAQ。
在 2.6.2* 中,/proc/interrupts 再次擴充套件。這次的目標是使 /proc/interrupts 顯示系統使用的每個 IRQ 向量,而不僅僅是那些被認為是“最重要”的向量。新的向量是
- THR
當機器檢查閾值計數器(通常計算記憶體或快取的 ECC 校正錯誤)超過可配置閾值時引發的中斷。僅在某些系統上可用。
- TRM
當 CPU 的溫度閾值被超過時,會發生熱事件中斷。當溫度恢復正常時,也可能會生成此中斷。
- SPU
偽中斷是某些 IO 裝置在 APIC 完全處理之前引發然後降低的中斷。因此,APIC 會看到中斷,但不知道它來自哪個裝置。對於這種情況,APIC 將生成 IRQ 向量為 0xff 的中斷。這也可能是由晶片組錯誤引起的。
- RES、CAL、TLB
重新排程、呼叫和 TLB 重新整理中斷會根據作業系統的需要從一個 CPU 傳送到另一個 CPU。通常,核心開發人員和感興趣的使用者使用它們的統計資訊來確定給定型別的中斷的發生。
上述 IRQ 向量僅在相關時顯示。例如,閾值向量在 x86_64 平臺上不存在。當系統是單處理器時,其他向量會被抑制。截至撰寫本文時,只有 i386 和 x86_64 平臺支援新的 IRQ 向量顯示。
在 2.4 中,/proc/irq 目錄的引入具有一定的意義。它可以用於設定 IRQ 到 CPU 的親和性。這意味著您可以將 IRQ“掛鉤”到只有一個 CPU,或者排除一個 CPU 處理 IRQ。irq 子目錄的內容是每個 IRQ 的一個子目錄和兩個檔案:default_smp_affinity 和 prof_cpu_mask。
例如
> ls /proc/irq/
0 10 12 14 16 18 2 4 6 8 prof_cpu_mask
1 11 13 15 17 19 3 5 7 9 default_smp_affinity
> ls /proc/irq/0/
smp_affinity
smp_affinity 是一個位掩碼,您可以在其中指定哪些 CPU 可以處理 IRQ。您可以透過執行以下操作來設定它
> echo 1 > /proc/irq/10/smp_affinity
這意味著只有第一個 CPU 會處理 IRQ,但您也可以 echo 5,這意味著只有第一個和第三個 CPU 可以處理 IRQ。
預設情況下,每個 smp_affinity 檔案的內容都相同
> cat /proc/irq/0/smp_affinity
ffffffff
還有另一個介面 smp_affinity_list,它允許指定 CPU 範圍而不是位掩碼
> cat /proc/irq/0/smp_affinity_list
1024-1031
default_smp_affinity 掩碼適用於所有非活動 IRQ,這些 IRQ 是尚未分配/啟用的 IRQ,因此缺少 /proc/irq/[0-9]* 目錄。
SMP 系統上的節點檔案顯示使用 IRQ 的裝置報告自身所連線到的節點。此硬體區域性性資訊不包括有關任何可能的驅動程式區域性性首選項的資訊。
prof_cpu_mask 指定系統範圍的分析器要分析哪些 CPU。預設值為 ffffffff(如果只有 32 個 CPU,則為所有 CPU)。
IRQ 的路由方式由 IO-APIC 處理,並且在所有允許處理它的 CPU 之間進行輪詢。與往常一樣,核心比您擁有更多資訊,並且比您做得更好,因此預設值幾乎是每個人的最佳選擇。[請注意,這僅適用於那些支援“輪詢”中斷分配的 IO-APIC。]
/proc 中還有三個更重要的子目錄:net、scsi 和 sys。一般規則是,這些目錄的內容,甚至存在,取決於您的核心配置。如果未啟用 SCSI,則 scsi 目錄可能不存在。net 也是如此,只有在正在執行的核心中存在網路支援時才存在。
slabinfo 檔案提供有關 slab 級別的記憶體使用情況的資訊。在 2.2 版本中,Linux 使用 slab 池進行頁面級別以上的記憶體管理。常用物件有它們自己的 slab 池(例如,網路緩衝區、目錄快取等)。
> cat /proc/buddyinfo
Node 0, zone DMA 0 4 5 4 4 3 ...
Node 0, zone Normal 1 0 0 1 101 8 ...
Node 0, zone HighMem 2 0 0 1 1 0 ...
外部碎片在某些工作負載下是一個問題,buddyinfo 是一個有用的工具,可以幫助診斷這些問題。Buddyinfo 將為您提供關於您可以安全分配多大的區域的線索,或者為什麼先前的分配失敗。
每一列代表可用特定順序的頁面數。在這種情況下,ZONE_DMA 中有 0 個 2^0*PAGE_SIZE 的塊可用,ZONE_DMA 中有 4 個 2^1*PAGE_SIZE 的塊,ZONE_NORMAL 中有 101 個 2^4*PAGE_SIZE 的塊可用,等等...
有關外部碎片化的更多資訊可以在 pagetypeinfo 中找到
> cat /proc/pagetypeinfo
Page block order: 9
Pages per block: 512
Free pages count per migrate type at order 0 1 2 3 4 5 6 7 8 9 10
Node 0, zone DMA, type Unmovable 0 0 0 1 1 1 1 1 1 1 0
Node 0, zone DMA, type Reclaimable 0 0 0 0 0 0 0 0 0 0 0
Node 0, zone DMA, type Movable 1 1 2 1 2 1 1 0 1 0 2
Node 0, zone DMA, type Reserve 0 0 0 0 0 0 0 0 0 1 0
Node 0, zone DMA, type Isolate 0 0 0 0 0 0 0 0 0 0 0
Node 0, zone DMA32, type Unmovable 103 54 77 1 1 1 11 8 7 1 9
Node 0, zone DMA32, type Reclaimable 0 0 2 1 0 0 0 0 1 0 0
Node 0, zone DMA32, type Movable 169 152 113 91 77 54 39 13 6 1 452
Node 0, zone DMA32, type Reserve 1 2 2 2 2 0 1 1 1 1 0
Node 0, zone DMA32, type Isolate 0 0 0 0 0 0 0 0 0 0 0
Number of blocks type Unmovable Reclaimable Movable Reserve Isolate
Node 0, zone DMA 2 0 5 1 0
Node 0, zone DMA32 41 6 967 2 0
核心中避免碎片化的方法是將不同遷移型別的頁面分組到稱為頁面塊的相同連續記憶體區域中。頁面塊通常是預設大頁面的大小,例如 X86-64 上為 2MB。透過基於頁面移動的能力對頁面進行分組,核心可以在頁面塊中回收頁面以滿足高階分配。
pagetypinfo 以頁面塊大小的資訊開始。然後,它提供與 buddyinfo 相同型別的資訊,但按遷移型別細分,並以每種型別的頁面塊存在多少個的詳細資訊結束。
如果 min_free_kbytes 已正確調整(來自 libhugetlbfs 的 hugeadm 所做的建議 https://github.com/libhugetlbfs/libhugetlbfs/),則可以估計在給定時間點可以分配的大頁面數量。除非記憶體已被 mlock(),否則所有“可移動”塊都應該是可分配的。某些“可回收”塊也應該是可分配的,儘管可能需要回收大量檔案系統元資料才能實現這一點。
allocinfo¶
提供有關程式碼庫中所有位置的記憶體分配的資訊。程式碼中的每個分配都由其原始檔、行號、模組(如果來自可載入模組)和呼叫分配的函式標識。報告每個位置分配的位元組數和呼叫次數。第一行指示檔案版本,第二行是檔案中的標題列表欄位。
示例輸出。
> tail -n +3 /proc/allocinfo | sort -rn
127664128 31168 mm/page_ext.c:270 func:alloc_page_ext
56373248 4737 mm/slub.c:2259 func:alloc_slab_page
14880768 3633 mm/readahead.c:247 func:page_cache_ra_unbounded
14417920 3520 mm/mm_init.c:2530 func:alloc_large_system_hash
13377536 234 block/blk-mq.c:3421 func:blk_mq_alloc_rqs
11718656 2861 mm/filemap.c:1919 func:__filemap_get_folio
9192960 2800 kernel/fork.c:307 func:alloc_thread_stack_node
4206592 4 net/netfilter/nf_conntrack_core.c:2567 func:nf_ct_alloc_hashtable
4136960 1010 drivers/staging/ctagmod/ctagmod.c:20 [ctagmod] func:ctagmod_start
3940352 962 mm/memory.c:4214 func:alloc_anon_folio
2894464 22613 fs/kernfs/dir.c:615 func:__kernfs_new_node
...
meminfo¶
提供有關記憶體的分配和利用率的資訊。這因體系結構和編譯選項而異。此處報告的一些計數器重疊。非重疊計數器報告的記憶體可能不會加到總記憶體使用量,並且某些工作負載的差異可能很大。在許多情況下,有其他方法可以使用子系統特定介面找到額外的記憶體,例如 /proc/net/sockstat 用於 TCP 記憶體分配。
示例輸出。您可能沒有所有這些欄位。
> cat /proc/meminfo
MemTotal: 32858820 kB
MemFree: 21001236 kB
MemAvailable: 27214312 kB
Buffers: 581092 kB
Cached: 5587612 kB
SwapCached: 0 kB
Active: 3237152 kB
Inactive: 7586256 kB
Active(anon): 94064 kB
Inactive(anon): 4570616 kB
Active(file): 3143088 kB
Inactive(file): 3015640 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Zswap: 1904 kB
Zswapped: 7792 kB
Dirty: 12 kB
Writeback: 0 kB
AnonPages: 4654780 kB
Mapped: 266244 kB
Shmem: 9976 kB
KReclaimable: 517708 kB
Slab: 660044 kB
SReclaimable: 517708 kB
SUnreclaim: 142336 kB
KernelStack: 11168 kB
PageTables: 20540 kB
SecPageTables: 0 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 16429408 kB
Committed_AS: 7715148 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 40444 kB
VmallocChunk: 0 kB
Percpu: 29312 kB
EarlyMemtestBad: 0 kB
HardwareCorrupted: 0 kB
AnonHugePages: 4149248 kB
ShmemHugePages: 0 kB
ShmemPmdMapped: 0 kB
FileHugePages: 0 kB
FilePmdMapped: 0 kB
CmaTotal: 0 kB
CmaFree: 0 kB
Unaccepted: 0 kB
Balloon: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
Hugetlb: 0 kB
DirectMap4k: 401152 kB
DirectMap2M: 10008576 kB
DirectMap1G: 24117248 kB
- MemTotal
總可用 RAM(即物理 RAM 減去一些保留位和核心二進位制程式碼)
- MemFree
總空閒 RAM。在高記憶體系統中,是 LowFree+HighFree 的總和
- MemAvailable
無需交換即可啟動新應用程式的可用記憶體估計值。從 MemFree、SReclaimable、檔案 LRU 列表的大小以及每個區域的低水位線計算得出。該估計考慮了系統需要一些頁面快取才能良好執行,並且由於某些專案正在使用中,並非所有可回收的 slab 都將可回收。這些因素的影響因系統而異。
- Buffers
用於原始磁碟塊的相對臨時儲存不應變得非常大(大約 20MB 左右)
- Cached
從磁碟讀取的檔案(頁面快取)以及 tmpfs 和 shmem 的記憶體快取。不包括 SwapCached。
- SwapCached
曾經被交換出去的記憶體,又被交換回來,但仍然在交換檔案中(如果需要記憶體,則不需要再次交換出去,因為它已經在交換檔案中。這節省了 I/O)
- Active
最近使用的記憶體,通常除非絕對必要,否則不會回收。
- Inactive
最近較少使用的記憶體。它更有資格被回收用於其他目的
- Unevictable
為使用者空間分配的無法回收的記憶體,例如 mlocked 頁面、ramfs 後備頁面、秘密 memfd 頁面等。
- Mlocked
用 mlock() 鎖定的記憶體。
- HighTotal, HighFree
高記憶體是物理記憶體中 ~860MB 以上的所有記憶體。高記憶體區域供使用者空間程式或頁面快取使用。核心必須使用技巧來訪問此記憶體,使其訪問速度低於低記憶體。
- LowTotal, LowFree
低記憶體是可以用於高記憶體可以使用的所有東西的記憶體,但它也可以供核心用於其自己的資料結構。在許多其他方面,Slab 中的所有東西都是從這裡分配的。當您耗盡低記憶體時,會發生糟糕的事情。
- SwapTotal
可用的交換空間總量
- SwapFree
已從 RAM 中驅逐的記憶體,暫時位於磁碟上
- Zswap
zswap 後端消耗的記憶體(壓縮大小)
- Zswapped
儲存在 zswap 中的匿名記憶體量(原始大小)
- Dirty
等待寫回磁碟的記憶體
- Writeback
正在積極寫回磁碟的記憶體
- AnonPages
對映到使用者空間頁表中的非檔案後備頁面。請注意,某些核心配置可能會將較大分配中的所有頁面(例如,THP)視為“已對映”,只要映射了單個頁面即可。
- Mapped
已進行 mmap 的檔案,例如庫。請注意,某些核心配置可能會將較大分配中的所有頁面(例如,THP)視為“已對映”,只要映射了單個頁面即可。
- Shmem
共享記憶體 (shmem) 和 tmpfs 使用的總記憶體
- KReclaimable
核心將在記憶體壓力下嘗試回收的核心分配。包括 SReclaimable(如下)和其他具有收縮器的直接分配。
- Slab
核心資料結構快取
- SReclaimable
Slab 的一部分,可以回收,例如快取
- SUnreclaim
Slab 的一部分,無法在記憶體壓力下回收
- KernelStack
所有任務的核心堆疊消耗的記憶體
- PageTables
使用者空間頁表消耗的記憶體
- SecPageTables
二級頁表消耗的記憶體,目前包括 x86 和 arm64 上的 KVM mmu 和 IOMMU 分配。
- NFS_Unstable
始終為零。以前計算的已寫入伺服器但尚未提交到穩定儲存的頁面。
- Bounce
用於塊裝置“反彈緩衝區”的記憶體
- WritebackTmp
FUSE 用於臨時寫回緩衝區的記憶體
- CommitLimit
基於過度提交率 ('vm.overcommit_ratio'),這是當前可用於在系統上分配的記憶體總量。只有啟用嚴格的過度提交記帳('vm.overcommit_memory' 中的模式 2)時,才遵守此限制。
CommitLimit 使用以下公式計算
CommitLimit = ([total RAM pages] - [total huge TLB pages]) * overcommit_ratio / 100 + [total swap pages]例如,在物理 RAM 為 1G、交換空間為 7G 且 vm.overcommit_ratio 為 30 的系統上,將產生 7.3G 的 CommitLimit。
有關更多詳細資訊,請參閱 mm/overcommit-accounting 中的記憶體過度提交文件。
- Committed_AS
當前在系統上分配的記憶體量。提交的記憶體是程序分配的所有記憶體的總和,即使它們尚未“使用”它。malloc() 1G 記憶體但僅觸控其中 300M 的程序將顯示為使用 1G。此 1G 記憶體已由 VM“提交”並可隨時被分配應用程式使用。如果在系統上啟用了嚴格的過度提交('vm.overcommit_memory' 中的模式 2),則不允許超過 CommitLimit(上面詳述)的分配。如果需要保證程序在成功分配記憶體後不會因缺少記憶體而失敗,這將非常有用。
- VmallocTotal
vmalloc 虛擬地址空間的總大小
- VmallocUsed
已使用的 vmalloc 區域量
- VmallocChunk
空閒的 vmalloc 區域的最大連續塊
- Percpu
分配給用於支援 percpu 分配的 percpu 分配器的記憶體。此統計資訊不包括元資料的成本。
- EarlyMemtestBad
在早期記憶體測試中識別為已損壞的 RAM/記憶體量(以 kB 為單位)。如果未執行記憶體測試,則根本不會顯示此欄位。大小永遠不會向下舍入到 0 kB。這意味著如果報告了 0 kB,您可以安全地假設至少有一個記憶體測試透過,並且沒有透過找到 RAM 的單個錯誤位元組。
- HardwareCorrupted
核心識別為已損壞的 RAM/記憶體量(以 KB 為單位)。
- AnonHugePages
對映到使用者空間頁表中的非檔案後備大頁面
- ShmemHugePages
使用大頁面分配的共享記憶體 (shmem) 和 tmpfs 使用的記憶體
- ShmemPmdMapped
使用大頁面對映到使用者空間的共享記憶體
- FileHugePages
使用大頁面分配的檔案系統資料(頁面快取)使用的記憶體
- FilePmdMapped
使用大頁面對映到使用者空間的頁面快取
- CmaTotal
為連續記憶體分配器 (CMA) 保留的記憶體
- CmaFree
CMA 保留中的剩餘空閒記憶體
- Unaccepted
訪客尚未接受的記憶體
- Balloon
VM Balloon Drivers 返回給主機的記憶體
- HugePages_Total, HugePages_Free, HugePages_Rsvd, HugePages_Surp, Hugepagesize, Hugetlb
請參閱 HugeTLB 頁面。
- DirectMap4k, DirectMap2M, DirectMap1G
核心 RAM 身份對映中使用的頁表大小細分
vmallocinfo¶
提供有關 vmalloced/vmaped 區域的資訊。每個區域一行,包含區域的虛擬地址範圍、大小(以位元組為單位)、建立者的呼叫者資訊以及可選資訊(具體取決於區域的型別)
> cat /proc/vmallocinfo
0xffffc20000000000-0xffffc20000201000 2101248 alloc_large_system_hash+0x204 ...
/0x2c0 pages=512 vmalloc N0=128 N1=128 N2=128 N3=128
0xffffc20000201000-0xffffc20000302000 1052672 alloc_large_system_hash+0x204 ...
/0x2c0 pages=256 vmalloc N0=64 N1=64 N2=64 N3=64
0xffffc20000302000-0xffffc20000304000 8192 acpi_tb_verify_table+0x21/0x4f...
phys=7fee8000 ioremap
0xffffc20000304000-0xffffc20000307000 12288 acpi_tb_verify_table+0x21/0x4f...
phys=7fee7000 ioremap
0xffffc2000031d000-0xffffc2000031f000 8192 init_vdso_vars+0x112/0x210
0xffffc2000031f000-0xffffc2000032b000 49152 cramfs_uncompress_init+0x2e ...
/0x80 pages=11 vmalloc N0=3 N1=3 N2=2 N3=3
0xffffc2000033a000-0xffffc2000033d000 12288 sys_swapon+0x640/0xac0 ...
pages=2 vmalloc N1=2
0xffffc20000347000-0xffffc2000034c000 20480 xt_alloc_table_info+0xfe ...
/0x130 [x_tables] pages=4 vmalloc N0=4
0xffffffffa0000000-0xffffffffa000f000 61440 sys_init_module+0xc27/0x1d00 ...
pages=14 vmalloc N2=14
0xffffffffa000f000-0xffffffffa0014000 20480 sys_init_module+0xc27/0x1d00 ...
pages=4 vmalloc N1=4
0xffffffffa0014000-0xffffffffa0017000 12288 sys_init_module+0xc27/0x1d00 ...
pages=2 vmalloc N1=2
0xffffffffa0017000-0xffffffffa0022000 45056 sys_init_module+0xc27/0x1d00 ...
pages=10 vmalloc N0=10
softirqs¶
提供自啟動時間以來,每個 CPU 服務軟中斷處理程式的計數。
> cat /proc/softirqs
CPU0 CPU1 CPU2 CPU3
HI: 0 0 0 0
TIMER: 27166 27120 27097 27034
NET_TX: 0 0 0 17
NET_RX: 42 0 0 39
BLOCK: 0 0 107 1121
TASKLET: 0 0 0 290
SCHED: 27035 26983 26971 26746
HRTIMER: 0 0 0 0
RCU: 1678 1769 2178 2250
1.3 /proc/net 中的網路資訊¶
子目錄 /proc/net 遵循通常的模式。表 1-8 顯示瞭如果您將核心配置為支援 IPv6,您將獲得的額外值。表 1-9 列出了檔案及其含義。
檔案 |
內容 |
|---|---|
udp6 |
UDP 套接字 (IPv6) |
tcp6 |
TCP 套接字 (IPv6) |
raw6 |
原始裝置統計資訊 (IPv6) |
igmp6 |
此主機加入的 IP 組播地址 (IPv6) |
if_inet6 |
IPv6 介面地址列表 |
ipv6_route |
IPv6 的核心路由表 |
rt6_stats |
全域性 IPv6 路由表統計資訊 |
sockstat6 |
套接字統計資訊 (IPv6) |
snmp6 |
Snmp 資料 (IPv6) |
檔案 |
內容 |
|---|---|
arp |
核心 ARP 表 |
dev |
具有統計資訊的網路裝置 |
dev_mcast |
裝置正在偵聽的 Layer2 組播組(介面索引、標籤、引用數、繫結地址數)。 |
dev_stat |
網路裝置狀態 |
ip_fwchains |
防火牆鏈鏈路 |
ip_fwnames |
防火牆鏈名稱 |
ip_masq |
包含偽裝表的目錄 |
ip_masquerade |
主要偽裝表 |
netstat |
網路統計資訊 |
raw |
原始裝置統計資訊 |
route |
核心路由表 |
rpc |
包含 rpc 資訊的目錄 |
rt_cache |
路由快取 |
snmp |
SNMP 資料 |
sockstat |
套接字統計資訊 |
softnet_stat |
聯機 CPU 的每個 CPU 的傳入資料包佇列統計資訊 |
tcp |
TCP 套接字 |
udp |
UDP 套接字 |
unix |
UNIX 域套接字 |
wireless |
無線介面資料 (Wavelan 等) |
igmp |
此主機加入的 IP 組播地址 |
psched |
全域性資料包排程程式引數。 |
netlink |
PF_NETLINK 套接字列表 |
ip_mr_vifs |
組播虛擬介面列表 |
ip_mr_cache |
組播路由快取列表 |
您可以使用此資訊來檢視系統中可用的網路裝置以及透過這些裝置路由的流量
> cat /proc/net/dev
Inter-|Receive |[...
face |bytes packets errs drop fifo frame compressed multicast|[...
lo: 908188 5596 0 0 0 0 0 0 [...
ppp0:15475140 20721 410 0 0 410 0 0 [...
eth0: 614530 7085 0 0 0 0 0 1 [...
...] Transmit
...] bytes packets errs drop fifo colls carrier compressed
...] 908188 5596 0 0 0 0 0 0
...] 1375103 17405 0 0 0 0 0 0
...] 1703981 5535 0 0 0 3 0 0
此外,每個通道繫結介面都有自己的目錄。例如,bond0 裝置將有一個名為 /proc/net/bond0/ 的目錄。它將包含特定於該繫結的資訊,例如繫結的當前從屬裝置、從屬裝置的連結狀態以及從屬裝置連結失敗的次數。
1.4 SCSI 資訊¶
如果您的系統中有一個 SCSI 或 ATA 主機介面卡,您將在 /proc/scsi 中找到一個以該介面卡的驅動程式命名的子目錄。您還將在 /proc/scsi 中看到所有已識別的 SCSI 裝置列表
>cat /proc/scsi/scsi
Attached devices:
Host: scsi0 Channel: 00 Id: 00 Lun: 00
Vendor: IBM Model: DGHS09U Rev: 03E0
Type: Direct-Access ANSI SCSI revision: 03
Host: scsi0 Channel: 00 Id: 06 Lun: 00
Vendor: PIONEER Model: CD-ROM DR-U06S Rev: 1.04
Type: CD-ROM ANSI SCSI revision: 02
以驅動程式命名的目錄為系統中找到的每個介面卡都有一個檔案。這些檔案包含有關控制器的資訊,包括使用的 IRQ 和 IO 地址範圍。顯示的資訊量取決於您使用的介面卡。該示例顯示了 Adaptec AHA-2940 SCSI 介面卡的輸出
> cat /proc/scsi/aic7xxx/0
Adaptec AIC7xxx driver version: 5.1.19/3.2.4
Compile Options:
TCQ Enabled By Default : Disabled
AIC7XXX_PROC_STATS : Disabled
AIC7XXX_RESET_DELAY : 5
Adapter Configuration:
SCSI Adapter: Adaptec AHA-294X Ultra SCSI host adapter
Ultra Wide Controller
PCI MMAPed I/O Base: 0xeb001000
Adapter SEEPROM Config: SEEPROM found and used.
Adaptec SCSI BIOS: Enabled
IRQ: 10
SCBs: Active 0, Max Active 2,
Allocated 15, HW 16, Page 255
Interrupts: 160328
BIOS Control Word: 0x18b6
Adapter Control Word: 0x005b
Extended Translation: Enabled
Disconnect Enable Flags: 0xffff
Ultra Enable Flags: 0x0001
Tag Queue Enable Flags: 0x0000
Ordered Queue Tag Flags: 0x0000
Default Tag Queue Depth: 8
Tagged Queue By Device array for aic7xxx host instance 0:
{255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255}
Actual queue depth per device for aic7xxx host instance 0:
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
Statistics:
(scsi0:0:0:0)
Device using Wide/Sync transfers at 40.0 MByte/sec, offset 8
Transinfo settings: current(12/8/1/0), goal(12/8/1/0), user(12/15/1/0)
Total transfers 160151 (74577 reads and 85574 writes)
(scsi0:0:6:0)
Device using Narrow/Sync transfers at 5.0 MByte/sec, offset 15
Transinfo settings: current(50/15/0/0), goal(50/15/0/0), user(50/15/0/0)
Total transfers 0 (0 reads and 0 writes)
1.5 /proc/parport 中的並行埠資訊¶
目錄 /proc/parport 包含有關係統並行埠的資訊。它為每個埠都有一個子目錄,以埠號 (0,1,2,...) 命名。
這些目錄包含表 1-10 中顯示的四個檔案。
檔案 |
內容 |
|---|---|
autoprobe |
已獲得的任何 IEEE-1284 裝置 ID 資訊。 |
devices |
使用該埠的裝置驅動程式列表。裝置當前正在使用該埠的名稱旁邊會出現一個 +(可能不會出現在任何裝置旁邊)。 |
hardware |
並行埠的基本地址、IRQ 線和 DMA 通道。 |
irq |
parport 正在用於該埠的 IRQ。這是一個單獨的檔案,允許您透過寫入一個新值(IRQ 號或 none)來更改它。 |
1.6 /proc/tty 中的 TTY 資訊¶
有關可用和實際使用的 tty 的資訊可以在目錄 /proc/tty 中找到。您將在此目錄中找到驅動程式和線路規程的條目,如表 1-11 所示。
檔案 |
內容 |
|---|---|
drivers |
驅動程式列表及其使用情況 |
ldiscs |
註冊的線路規程 |
driver/serial |
單個 tty 線路的使用統計資訊和狀態 |
要檢視當前正在使用的 tty,您可以簡單地檢視檔案 /proc/tty/drivers
> cat /proc/tty/drivers
pty_slave /dev/pts 136 0-255 pty:slave
pty_master /dev/ptm 128 0-255 pty:master
pty_slave /dev/ttyp 3 0-255 pty:slave
pty_master /dev/pty 2 0-255 pty:master
serial /dev/cua 5 64-67 serial:callout
serial /dev/ttyS 4 64-67 serial
/dev/tty0 /dev/tty0 4 0 system:vtmaster
/dev/ptmx /dev/ptmx 5 2 system
/dev/console /dev/console 5 1 system:console
/dev/tty /dev/tty 5 0 system:/dev/tty
unknown /dev/tty 4 1-63 console
1.7 /proc/stat 中的其他核心統計資訊¶
有關核心活動的各種資訊可在 /proc/stat 檔案中找到。此檔案中報告的所有數字都是自系統首次啟動以來的聚合值。要快速檢視,只需 cat 該檔案
> cat /proc/stat
cpu 237902850 368826709 106375398 1873517540 1135548 0 14507935 0 0 0
cpu0 60045249 91891769 26331539 468411416 495718 0 5739640 0 0 0
cpu1 59746288 91759249 26609887 468860630 312281 0 4384817 0 0 0
cpu2 59489247 92985423 26904446 467808813 171668 0 2268998 0 0 0
cpu3 58622065 92190267 26529524 468436680 155879 0 2114478 0 0 0
intr 8688370575 8 3373 0 0 0 0 0 0 1 40791 0 0 353317 0 0 0 0 224789828 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 190974333 41958554 123983334 43 0 224593 0 0 0 <more 0's deleted>
ctxt 22848221062
btime 1605316999
processes 746787147
procs_running 2
procs_blocked 0
softirq 12121874454 100099120 3938138295 127375644 2795979 187870761 0 173808342 3072582055 52608 224184354
第一個“cpu”行聚合了所有其他“cpuN”行中的數字。這些數字標識了 CPU 花費在執行不同型別工作上的時間量。時間單位為 USER_HZ(通常為百分之一秒)。從左到右,各列的含義如下
user:在使用者模式下執行的普通程序
nice:在使用者模式下執行的 niced 程序
system:在核心模式下執行的程序
idle:無所事事
iowait:總之,iowait 代表等待 I/O 完成。但存在幾個問題
CPU 將不會等待 I/O 完成,iowait 是任務等待 I/O 完成的時間。當 CPU 由於未完成的任務 I/O 而進入空閒狀態時,將在該 CPU 上排程另一個任務。
在多核 CPU 中,等待 I/O 完成的任務不在任何 CPU 上執行,因此每個 CPU 的 iowait 難以計算。
/proc/stat 中 iowait 欄位的值將在某些條件下減少。
因此,透過從 /proc/stat 讀取 iowait 是不可靠的。
irq:服務中斷
softirq:服務軟中斷
steal:非自願等待
guest:執行普通訪客
guest_nice:執行 niced 訪客
“intr”行提供自啟動時間以來服務的中斷計數,用於每個可能的系統中斷。第一列是服務的所有中斷的總數,包括未編號的特定於體系結構的中斷;每個後續列是該特定編號中斷的總數。未編號的中斷不會顯示,只會彙總到總數中。
“ctxt”行給出所有 CPU 上的上下文切換總數。
“btime”行給出系統啟動的時間,以自 Unix 紀元以來的秒數表示。
“processes”行給出建立的程序和執行緒數,其中包括(但不限於)透過呼叫 fork() 和 clone() 系統呼叫建立的程序和執行緒。
“procs_running”行給出正在執行或準備執行的執行緒總數(即,可執行執行緒的總數)。
“procs_blocked”行給出當前被阻止的程序數,等待 I/O 完成。
“softirq”行提供自啟動時間以來服務的軟中斷計數,用於每個可能的系統軟中斷。第一列是服務的所有軟中斷的總數;每個後續列是該特定軟中斷的總數。
1.8 Ext4 檔案系統引數¶
有關已掛載的 ext4 檔案系統的資訊可以在 /proc/fs/ext4 中找到。每個已掛載的檔案系統將在 /proc/fs/ext4 中基於其裝置名稱(即,/proc/fs/ext4/hdc 或 /proc/fs/ext4/sda9 或 /proc/fs/ext4/dm-0)都有一個目錄。表 1-12 顯示了每個按裝置目錄中的檔案。
檔案 |
內容 |
mb_groups |
多塊分配器空閒塊夥伴快取的詳細資訊 |
1.9 /proc/consoles¶
顯示已註冊的系統控制檯線路。
要檢視當前用於系統控制檯 /dev/console 的字元裝置線路,您可以簡單地檢視檔案 /proc/consoles
> cat /proc/consoles
tty0 -WU (ECp) 4:7
ttyS0 -W- (Ep) 4:64
各列如下
device |
裝置名稱 |
|---|---|
operations |
|
flags |
|
major:minor |
裝置的主裝置號和次裝置號,用冒號分隔 |
總結¶
/proc 檔案系統提供有關執行系統的資訊。它不僅允許訪問程序資料,還允許您透過讀取層次結構中的檔案來請求核心狀態。
/proc 的目錄結構反映了資訊的型別,並使查詢特定資料變得容易(如果不是顯而易見)。
第 2 章:修改系統引數¶
在本章中¶
透過寫入 /proc/sys 中找到的檔案來修改核心引數
探索修改某些引數的檔案
審查 /proc/sys 檔案樹
/proc 中非常有趣的一部分是目錄 /proc/sys。這不僅是資訊的來源,還允許您更改核心中的引數。嘗試這樣做時要非常小心。您可以最佳化系統,但也可能導致系統崩潰。永遠不要在生產系統上更改核心引數。設定開發機器並進行測試,以確保一切按您希望的方式工作。一旦出現錯誤,您可能別無選擇,只能重新啟動機器。
要更改值,只需將新值 echo 到檔案中。您需要 root 許可權才能執行此操作。您可以建立自己的啟動指令碼來在每次系統啟動時執行此操作。
/proc/sys 中的檔案可用於微調和監視 Linux 核心操作中的雜項和常規事項。由於某些檔案可能會無意中擾亂您的系統,因此建議在實際進行調整之前閱讀文件和原始碼。在任何情況下,寫入這些檔案時都要非常小心。/proc 中的條目在 2.1.* 和 2.2 核心之間可能會略有變化,因此如果有任何疑問,請檢視目錄 linux/Documentation 中的核心文件。本章主要基於 pre 2.2 核心中包含的文件,並在 Linux 核心的 2.2.1 版本中成為其中的一部分。
請參閱:Documentation/admin-guide/sysctl/ 目錄以獲取這些條目的描述。
總結¶
核心行為的某些方面可以在執行時修改,而無需重新編譯核心,甚至無需重新啟動系統。/proc/sys 樹中的檔案不僅可以讀取,還可以修改。您可以使用 echo 命令將值寫入這些檔案,從而更改核心的預設設定。
第 3 章:按程序引數¶
3.1 /proc/<pid>/oom_adj & /proc/<pid>/oom_score_adj- 調整 oom-killer 分數¶
這些檔案可用於調整 badness 啟發式演算法,該演算法用於選擇在記憶體不足 (oom) 條件下要殺死的程序。
badness 啟發式演算法為每個候選任務分配一個值,範圍從 0(從不殺死)到 1000(始終殺死),以確定哪個程序是目標。這些單位大致是在該範圍內的一部分,程序可以根據對其當前記憶體和交換使用情況的估計來分配允許的記憶體。例如,如果一個任務正在使用所有允許的記憶體,它的 badness 分數將為 1000。如果它正在使用其允許記憶體的一半,它的分數將為 500。
“允許”記憶體量取決於呼叫 oom killer 的上下文。如果是由於分配任務的 cpuset 分配的記憶體已耗盡,則允許的記憶體表示分配給該 cpuset 的記憶體集。如果是由於 mempolicy 的節點已耗盡,則允許的記憶體表示 mempolicy 節點的集合。如果是由於達到了記憶體限制(或交換限制),則允許的記憶體是該配置的限制。最後,如果是由於整個系統記憶體不足,則允許的記憶體表示所有可分配的資源。
/proc/<pid>/oom_score_adj 的值新增到 badness 分數中,然後再用於確定要殺死的任務。可接受的值範圍從 -1000 (OOM_SCORE_ADJ_MIN) 到 +1000 (OOM_SCORE_ADJ_MAX)。這允許使用者空間透過始終首選某個任務或完全停用它來極化 oom 殺死首選項。可能的最低值 -1000 等效於完全停用該任務的 oom 殺死,因為它將始終報告 badness 分數為 0。
因此,使用者空間可以非常簡單地定義每個任務要考慮的記憶體量。例如,將 /proc/<pid>/oom_score_adj 值設定為 +500,大致相當於允許共享相同系統、cpuset、記憶體策略或記憶體控制器資源的其餘任務使用至少多 50% 的記憶體。另一方面,將值設定為 -500,大致相當於從任務允許的記憶體中扣除 50% 的記憶體,使其不被視為針對該任務的評分。
為了與以前的核心向後相容,/proc/<pid>/oom_adj 也可以用於調整 badness 分數。其可接受的值範圍為 -16 (OOM_ADJUST_MIN) 到 +15 (OOM_ADJUST_MAX),特殊值 -17 (OOM_DISABLE) 用於完全停用該任務的 OOM killing。其值與 /proc/<pid>/oom_score_adj 線性縮放。
/proc/<pid>/oom_score_adj 的值可能不會降低到 CAP_SYS_RESOURCE 程序設定的最後一個值以下。要將值降低到更低的值,需要 CAP_SYS_RESOURCE 許可權。
3.2 /proc/<pid>/oom_score - 顯示當前 OOM killer 分數¶
該檔案可用於檢查 OOM killer 為任何給定的 <pid> 使用的當前分數。將其與 /proc/<pid>/oom_score_adj 一起使用,以調整在記憶體不足的情況下應殺死哪個程序。
請注意,匯出的值包括 oom_score_adj,因此實際上範圍為 [0,2000]。
3.3 /proc/<pid>/io - 顯示 IO 統計欄位¶
此檔案包含每個正在執行的程序的 IO 統計資訊。
示例¶
test:/tmp # dd if=/dev/zero of=/tmp/test.dat &
[1] 3828
test:/tmp # cat /proc/3828/io
rchar: 323934931
wchar: 323929600
syscr: 632687
syscw: 632675
read_bytes: 0
write_bytes: 323932160
cancelled_write_bytes: 0
描述¶
rchar¶
I/O 計數器:讀取的字元數。此任務導致從儲存讀取的位元組數。這只是此程序傳遞給 read() 和 pread() 的位元組數之和。它包括諸如 tty IO 之類的東西,並且不受是否需要實際物理磁碟 IO 的影響(讀取可能已從 pagecache 滿足)。
wchar¶
I/O 計數器:寫入的字元數。此任務已導致或將導致寫入磁碟的位元組數。與 rchar 一樣,這裡也適用類似的注意事項。
syscr¶
I/O 計數器:讀取 syscalls。嘗試計算讀取 I/O 操作的數量,即諸如 read() 和 pread() 之類的 syscalls。
syscw¶
I/O 計數器:寫入 syscalls。嘗試計算寫入 I/O 操作的數量,即諸如 write() 和 pwrite() 之類的 syscalls。
read_bytes¶
I/O 計數器:讀取的位元組數。嘗試計算此程序真正導致從儲存層獲取的位元組數。在 submit_bio() 級別完成,因此對於塊支援的檔案系統來說是準確的。<請稍後新增關於 NFS 和 CIFS 的狀態>
write_bytes¶
I/O 計數器:寫入的位元組數。嘗試計算此程序導致傳送到儲存層的位元組數。這在頁面變髒時完成。
cancelled_write_bytes¶
這裡最大的不準確之處是 truncate。如果一個程序向一個檔案寫入 1MB,然後刪除該檔案,實際上不會執行任何寫出操作。但它將被計為導致 1MB 的寫入。換句話說:此程序透過截斷 pagecache 導致未發生的位元組數。一個任務也可以導致“負”IO。如果此任務截斷了一些髒 pagecache,那麼另一個任務已計入的(在其 write_bytes 中)一些 IO 將不會發生。我們可以直接從截斷任務的 write_bytes 中減去它,但這樣做會丟失資訊。
注意
在其當前的實現狀態下,這在 32 位機器上有點競爭:如果程序 A 讀取程序 B 的 /proc/pid/io,而程序 B 正在更新這些 64 位計數器之一,則程序 A 可能會看到中間結果。
有關此的更多資訊可以在 Documentation/accounting 中的 taskstats 文件中找到。
3.4 /proc/<pid>/coredump_filter - Core dump 過濾設定¶
當轉儲程序時,所有匿名記憶體都會寫入 core 檔案,只要 core 檔案的大小沒有限制。但是有時我們不想轉儲某些記憶體段,例如,巨大的共享記憶體或 DAX。相反,有時我們希望將檔案支援的記憶體段儲存到 core 檔案中,而不僅僅是個別檔案。
/proc/<pid>/coredump_filter 允許您自定義在轉儲 <pid> 程序時將轉儲哪些記憶體段。 coredump_filter 是記憶體型別的位掩碼。如果設定了位掩碼的一位,則會轉儲相應記憶體型別的記憶體段,否則不會轉儲。
支援以下 9 種記憶體型別
(bit 0) 匿名私有記憶體
(bit 1) 匿名共享記憶體
(bit 2) 檔案支援的私有記憶體
(bit 3) 檔案支援的共享記憶體
(bit 4) 檔案支援的私有記憶體區域中的 ELF 標頭頁面(僅當位 2 被清除時才有效)
(bit 5) hugetlb 私有記憶體
(bit 6) hugetlb 共享記憶體
(bit 7) DAX 私有記憶體
(bit 8) DAX 共享記憶體
請注意,MMIO 頁面(例如幀緩衝區)永遠不會轉儲,並且 vDSO 頁面始終會被轉儲,而與位掩碼狀態無關。
請注意,位 0-4 不影響 hugetlb 或 DAX 記憶體。 hugetlb 記憶體僅受位 5-6 影響,DAX 僅受位 7-8 影響。
coredump_filter 的預設值為 0x33;這意味著所有匿名記憶體段、ELF 標頭頁面和 hugetlb 私有記憶體都會被轉儲。
如果您不想轉儲附加到 pid 1234 的所有共享記憶體段,請將 0x31 寫入程序的 proc 檔案
$ echo 0x31 > /proc/1234/coredump_filter
建立新程序時,程序會從其父程序繼承位掩碼狀態。在程式執行之前設定 coredump_filter 很有用。例如
$ echo 0x7 > /proc/self/coredump_filter
$ ./some_program
3.5 /proc/<pid>/mountinfo - 關於掛載的資訊¶
此檔案包含以下形式的行
36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue
(1)(2)(3) (4) (5) (6) (n…m) (m+1)(m+2) (m+3) (m+4)
(1) mount ID: unique identifier of the mount (may be reused after umount)
(2) parent ID: ID of parent (or of self for the top of the mount tree)
(3) major:minor: value of st_dev for files on filesystem
(4) root: root of the mount within the filesystem
(5) mount point: mount point relative to the process's root
(6) mount options: per mount options
(n…m) optional fields: zero or more fields of the form "tag[:value]"
(m+1) separator: marks the end of the optional fields
(m+2) filesystem type: name of filesystem of the form "type[.subtype]"
(m+3) mount source: filesystem specific information or "none"
(m+4) super options: per super block options
解析器應忽略所有無法識別的可選欄位。當前可能的可選欄位有
shared:X |
掛載在對等組 X 中共享 |
master:X |
掛載是從對等組 X 的從屬 |
propagate_from:X |
掛載是從屬,並從對等組 X 接收傳播 [1] |
unbindable |
掛載是不可繫結的 |
有關掛載傳播的更多資訊,請參見
3.6 /proc/<pid>/comm & /proc/<pid>/task/<tid>/comm¶
這些檔案提供了一種訪問任務 comm 值的方法。它還允許任務設定其自身或其執行緒兄弟的 comm 值。與 cmdline 值相比,comm 值的大小有限,因此寫入任何長於核心 TASK_COMM_LEN(當前為 16 個字元,包括 NUL 終止符)的內容將導致 comm 值被截斷。
3.7 /proc/<pid>/task/<tid>/children - 關於任務子程序的資訊¶
此檔案提供了一種快速檢索由 <pid>/<tid> 對指向的任務的第一級子程序 pid 的方法。格式是以空格分隔的 pid 流。
請注意這裡的“第一級”——如果一個子程序有它自己的子程序,它們將不會在這裡列出;需要讀取 /proc/<children-pid>/task/<tid>/children 以獲得後代。
由於此介面旨在快速且廉價,因此它不保證提供精確的結果,並且某些子程序可能會被跳過,特別是如果它們在我們列印其 pid 後立即退出,因此如果需要精確的結果,則需要停止或凍結正在檢查的程序。
3.8 /proc/<pid>/fdinfo/<fd> - 關於開啟的檔案的資訊¶
此檔案提供與開啟的檔案關聯的資訊。常規檔案至少有四個欄位——“pos”、“flags”、“mnt_id” 和 “ino”。“pos” 表示開啟的檔案中當前的偏移量(十進位制形式)[有關詳細資訊,請參見 lseek(2)],“flags” 表示建立檔案時使用的八進位制 O_xxx 掩碼 [有關詳細資訊,請參見 open(2)],“mnt_id” 表示包含開啟的檔案的檔案系統的掛載 ID [有關詳細資訊,請參見 3.5 /proc/<pid>/mountinfo]。 “ino” 表示檔案的 inode 編號。
典型的輸出是
pos: 0
flags: 0100002
mnt_id: 19
ino: 63107
與檔案描述符關聯的所有鎖也會顯示在其 fdinfo 中
lock: 1: FLOCK ADVISORY WRITE 359 00:13:11691 0 EOF
諸如 eventfd、fsnotify、signalfd、epoll 之類的檔案除了常規的 pos/flags 對之外,還提供特定於它們所代表的物件的其他資訊。
Eventfd 檔案¶
pos: 0
flags: 04002
mnt_id: 9
ino: 63107
eventfd-count: 5a
其中 “eventfd-count” 是計數器的十六進位制值。
Signalfd 檔案¶
pos: 0
flags: 04002
mnt_id: 9
ino: 63107
sigmask: 0000000000000200
其中 “sigmask” 是與檔案關聯的訊號掩碼的十六進位制值。
Epoll 檔案¶
pos: 0
flags: 02
mnt_id: 9
ino: 63107
tfd: 5 events: 1d data: ffffffffffffffff pos:0 ino:61af sdev:7
其中 “tfd” 是目標檔案描述符編號(十進位制形式),“events” 是被監視的事件掩碼,“data” 是與目標關聯的資料 [有關更多詳細資訊,請參見 epoll(7)]。
“pos” 是目標檔案的當前偏移量(十進位制形式)[參見 lseek(2)],“ino” 和 “sdev” 是目標檔案所在的 inode 和裝置編號,均以十六進位制格式表示。
Fsnotify 檔案¶
對於 inotify 檔案,格式如下
pos: 0
flags: 02000000
mnt_id: 9
ino: 63107
inotify wd:3 ino:9e7e sdev:800013 mask:800afce ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:7e9e0000640d1b6d
其中 “wd” 是監視描述符(十進位制形式),即目標檔案描述符編號,“ino” 和 “sdev” 是目標檔案所在的 inode 和裝置, “mask” 是事件掩碼,所有這些都以十六進位制形式表示 [有關更多詳細資訊,請參見 inotify(7)]。
如果核心是用 exportfs 支援構建的,則目標檔案的路徑將被編碼為檔案控制代碼。檔案控制代碼由三個欄位 “fhandle-bytes”、“fhandle-type” 和 “f_handle” 提供,所有這些都以十六進位制格式表示。
如果核心在沒有 exportfs 支援的情況下構建,則檔案控制代碼將不會打印出來。
如果尚未附加任何 inotify 標記,則將省略 “inotify” 行。
對於 fanotify 檔案,格式為
pos: 0
flags: 02
mnt_id: 9
ino: 63107
fanotify flags:10 event-flags:0
fanotify mnt_id:12 mflags:40 mask:38 ignored_mask:40000003
fanotify ino:4f969 sdev:800013 mflags:0 mask:3b ignored_mask:40000000 fhandle-bytes:8 fhandle-type:1 f_handle:69f90400c275b5b4
其中 fanotify “flags” 和 “event-flags” 是 fanotify_init 呼叫中使用的值,“mnt_id” 是掛載點識別符號,“mflags” 是與標記關聯的標誌的值,這些標誌與事件掩碼分開跟蹤。“ino” 和 “sdev” 是目標 inode 和裝置,“mask” 是事件掩碼,“ignored_mask” 是要忽略的事件的掩碼。所有這些都以十六進位制格式表示。“mflags”、“mask” 和 “ignored_mask” 的合併提供了有關 fanotify_mark 呼叫中使用的標誌和掩碼的資訊 [有關詳細資訊,請參見 fsnotify 手冊頁]。
雖然前三行是強制性的且始終列印,但其餘行是可選的,如果尚未建立任何標記,則可以省略。
Timerfd 檔案¶
pos: 0
flags: 02
mnt_id: 9
ino: 63107
clockid: 0
ticks: 0
settime flags: 01
it_value: (0, 49406829)
it_interval: (1, 0)
其中 “clockid” 是時鐘型別,“ticks” 是發生的計時器到期次數 [有關詳細資訊,請參見 timerfd_create(2)]。“settime flags” 是用於設定計時器的八進位制形式的標誌 [有關詳細資訊,請參見 timerfd_settime(2)]。“it_value” 是計時器到期前的剩餘時間。“it_interval” 是計時器的間隔。請注意,可以使用 TIMER_ABSTIME 選項設定計時器,該選項將顯示在 “settime flags” 中,但 “it_value” 仍然顯示計時器的剩餘時間。
DMA 緩衝區檔案¶
pos: 0
flags: 04002
mnt_id: 9
ino: 63107
size: 32768
count: 2
exp_name: system-heap
其中 “size” 是 DMA 緩衝區的大小(以位元組為單位)。“count” 是 DMA 緩衝區檔案的檔案計數。“exp_name” 是 DMA 緩衝區匯出器的名稱。
3.9 /proc/<pid>/map_files - 關於記憶體對映檔案的資訊¶
此目錄包含表示程序正在維護的記憶體對映檔案的符號連結。示例輸出
| lr-------- 1 root root 64 Jan 27 11:24 333c600000-333c620000 -> /usr/lib64/ld-2.18.so
| lr-------- 1 root root 64 Jan 27 11:24 333c81f000-333c820000 -> /usr/lib64/ld-2.18.so
| lr-------- 1 root root 64 Jan 27 11:24 333c820000-333c821000 -> /usr/lib64/ld-2.18.so
| ...
| lr-------- 1 root root 64 Jan 27 11:24 35d0421000-35d0422000 -> /usr/lib64/libselinux.so.1
| lr-------- 1 root root 64 Jan 27 11:24 400000-41a000 -> /usr/bin/ls
連結的名稱表示對映的虛擬記憶體邊界,即 vm_area_struct::vm_start-vm_area_struct::vm_end。
map_files 的主要目的是以快速的方式檢索一組記憶體對映檔案,而不是解析 /proc/<pid>/maps 或 /proc/<pid>/smaps,這兩者都包含更多記錄。同時,可以開啟(2) 來自兩個程序列表的對映並比較它們的 inode 編號,以確定哪些匿名記憶體區域實際上是共享的。
3.10 /proc/<pid>/timerslack_ns - 任務 timerslack 值¶
此檔案提供任務的 timerslack 值(以納秒為單位)。此值指定可以延遲正常計時器的時間量,以便合併計時器並避免不必要的喚醒。
這允許調整任務的互動性與功耗之間的權衡。
將 0 寫入檔案會將任務的 timerslack 設定為預設值。
有效值範圍為 0 - ULLONG_MAX
應用程式設定該值必須具有 PTRACE_MODE_ATTACH_FSCREDS 級別的許可權才能更改指定的任務的 timerslack_ns 值。
3.11 /proc/<pid>/patch_state - Livepatch 修補操作狀態¶
啟用 CONFIG_LIVEPATCH 時,此檔案顯示任務的修補狀態值。
值“-1”表示沒有修補程式正在轉換中。
值“0”表示修補程式正在轉換中,並且任務未修補。如果要啟用修補程式,則任務尚未修補。如果要停用修補程式,則任務已取消修補。
值“1”表示修補程式正在轉換中,並且任務已修補。如果要啟用修補程式,則任務已修補。如果要停用修補程式,則任務尚未取消修補。
3.12 /proc/<pid>/arch_status - 任務架構特定狀態¶
啟用 CONFIG_PROC_PID_ARCH_STATUS 時,此檔案顯示任務的架構特定狀態。
示例¶
$ cat /proc/6753/arch_status
AVX512_elapsed_ms: 8
描述¶
x86 特定條目¶
AVX512_elapsed_ms¶
如果機器上支援 AVX512,則此條目顯示自上次記錄 AVX512 使用情況以來經過的毫秒數。該記錄在任務被排程出去時盡力而為地進行。這意味著該值取決於兩個因素
任務在 CPU 上花費的時間而沒有被排程出去。使用 CPU 隔離和單個可執行任務,這可能需要幾秒鐘。
自上次任務被排程出去以來的時間。根據被排程出去的原因(時間片耗盡、syscall ...),這可能需要任意長的時間。
因此,該值不能被認為是精確的和權威的資訊。使用此資訊的應用程式必須瞭解系統上的整體情況,以便確定任務是否是真正的 AVX512 使用者。可以使用效能計數器獲得精確的資訊。
值“-1”表示未記錄 AVX512 使用情況,因此該任務不太可能是 AVX512 使用者,但這取決於工作負載和排程情況,也可能是上面提到的假陰性。
3.13 /proc/<pid>/fd - 開啟檔案的符號連結列表¶
此目錄包含表示程序正在維護的開啟檔案的符號連結。示例輸出
lr-x------ 1 root root 64 Sep 20 17:53 0 -> /dev/null
l-wx------ 1 root root 64 Sep 20 17:53 1 -> /dev/null
lrwx------ 1 root root 64 Sep 20 17:53 10 -> 'socket:[12539]'
lrwx------ 1 root root 64 Sep 20 17:53 11 -> 'socket:[12540]'
lrwx------ 1 root root 64 Sep 20 17:53 12 -> 'socket:[12542]'
程序的開啟檔案數儲存在 /proc/<pid>/fd 的 stat() 輸出的 “size” 成員中,以便快速訪問。-------------------------------------------------------
3.14 /proc/<pid/ksm_stat - 關於程序的 ksm 狀態的資訊¶
啟用 CONFIG_KSM 時,每個程序都有此檔案,該檔案顯示 ksm 合併狀態的資訊。
示例¶
/ # cat /proc/self/ksm_stat
ksm_rmap_items 0
ksm_zero_pages 0
ksm_merging_pages 0
ksm_process_profit 0
ksm_merge_any: no
ksm_mergeable: no
描述¶
ksm_rmap_items¶
正在使用的 ksm_rmap_item 結構的數目。結構 ksm_rmap_item 儲存虛擬地址的反向對映資訊。 KSM 將為程序的每個 ksm 掃描頁面生成一個 ksm_rmap_item。
ksm_zero_pages¶
啟用 /sys/kernel/mm/ksm/use_zero_pages 時,它表示透過 KSM 合併了多少個空頁面與核心零頁面。
ksm_merging_pages¶
它表示此程序中有多少頁面參與 KSM 合併(不包括 ksm_zero_pages)。它與 /proc/<pid>/ksm_merging_pages 顯示的內容相同。
ksm_process_profit¶
KSM 帶來的利潤(節省的位元組)。 KSM 可以透過合併相同的頁面來節省記憶體,但也可以消耗額外的記憶體,因為它需要生成許多 rmap_items 來儲存每個掃描頁面的簡短 rmap 資訊。其中一些頁面可能被合併,但有些頁面可能在多次檢查後無法合併,這些都是無利可圖的記憶體消耗。
ksm_merge_any¶
它指定程序的 “mm” 是否由 prctl() 新增到 KSM 的候選列表,以及是否在程序級別完全啟用了 KSM 掃描。
ksm_mergeable¶
它指定程序的 mms 的任何 VMA 當前是否適用於 KSM。
有關 KSM 的更多資訊可以在 Kernel Samepage Merging 中找到。
第 4 章:配置 procfs¶
4.1 掛載選項¶
支援以下掛載選項
hidepid=
設定 /proc/<pid>/ 訪問模式。
gid=
設定授權學習程序資訊的組。
subset=
僅顯示 procfs 的指定子集。
hidepid=off 或 hidepid=0 表示經典模式 - 每個人都可以訪問所有 /proc/<pid>/ 目錄(預設)。
hidepid=noaccess 或 hidepid=1 表示使用者可能無法訪問任何 /proc/<pid>/ 目錄,但他們自己的目錄除外。現在可以保護敏感檔案(例如 cmdline、sched*、status)免受其他使用者的侵害。這使得無法瞭解任何使用者是否執行特定程式(如果該程式沒有透過其行為顯示自身)。作為額外的獎勵,由於其他使用者無法訪問 /proc/<pid>/cmdline,因此現在可以保護透過程式引數傳遞敏感資訊的編寫不佳的程式免受本地竊聽者的侵害。
hidepid=invisible 或 hidepid=2 表示 hidepid=1 加上所有 /proc/<pid>/ 對其他使用者將完全不可見。這並不意味著它隱藏了具有特定 pid 值的程序是否存在的事實(可以透過其他方式瞭解,例如透過 “kill -0 $PID”),但它隱藏了程序的 uid 和 gid,否則可以透過 stat()’ing /proc/<pid>/ 瞭解。這大大簡化了入侵者收集有關執行程序的資訊的任務,無論某些守護程式是否以提升的許可權執行,其他使用者是否執行某些敏感程式,其他使用者是否根本執行任何程式等等。
hidepid=ptraceable 或 hidepid=4 表示 procfs 應僅包含呼叫者可以 ptrace 的 /proc/<pid>/ 目錄。
gid= 定義了一個組,該組被授權瞭解程序資訊,否則 hidepid= 會禁止這樣做。如果您使用諸如 identd 之類的守護程式,該守護程式需要了解有關程序資訊的資訊,只需將 identd 新增到此組即可。
subset=pid 隱藏 procfs 中所有與任務無關的頂級檔案和目錄。
第 5 章:檔案系統行為¶
最初,在 pid 命名空間出現之前,procfs 是一個全域性檔案系統。這意味著系統中只有一個 procfs 例項。
當新增 pid 名稱空間時,會在每個 pid 名稱空間中掛載一個單獨的 procfs 例項。因此,procfs 掛載選項在同一名稱空間內的所有掛載點之間是全域性的
# grep ^proc /proc/mounts
proc /proc proc rw,relatime,hidepid=2 0 0
# strace -e mount mount -o hidepid=1 -t proc proc /tmp/proc
mount("proc", "/tmp/proc", "proc", 0, "hidepid=1") = 0
+++ exited with 0 +++
# grep ^proc /proc/mounts
proc /proc proc rw,relatime,hidepid=2 0 0
proc /tmp/proc proc rw,relatime,hidepid=2 0 0
並且僅在重新掛載 procfs 後,掛載選項才會更改所有掛載點
# mount -o remount,hidepid=1 -t proc proc /tmp/proc
# grep ^proc /proc/mounts
proc /proc proc rw,relatime,hidepid=1 0 0
proc /tmp/proc proc rw,relatime,hidepid=1 0 0
此行為與其他檔案系統的行為不同。
新的 procfs 行為更像其他檔案系統。每個 procfs 掛載都會建立一個新的 procfs 例項。掛載選項影響自己的 procfs 例項。這意味著有可能在同一個 pid 名稱空間中擁有多個 procfs 例項,這些例項顯示具有不同過濾選項的任務
# mount -o hidepid=invisible -t proc proc /proc
# mount -o hidepid=noaccess -t proc proc /tmp/proc
# grep ^proc /proc/mounts
proc /proc proc rw,relatime,hidepid=invisible 0 0
proc /tmp/proc proc rw,relatime,hidepid=noaccess 0 0