/proc文件系统 【ChatGPT】

发布时间 2023-12-10 23:21:10作者: 摩斯电码

/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文件系统的第一个“一站式”文档。它专注于Intel x86硬件,因此如果您正在寻找PPC、ARM、SPARC、AXP等功能,您可能找不到您要找的内容。它也仅涵盖IPv4网络,不涵盖IPv6或其他协议 - 抱歉。但是,欢迎添加和修补,并且如果您将它们发送给Bodo,它们将被添加到本文档中。

我们要感谢Alan Cox、Rik van Riel和Alexey Kuznetsov以及许多其他人为帮助编写本文档。我们还要特别感谢Andi Kleen提供的文档,我们在创建本文档时依赖了他的大量信息。感谢所有为Linux内核贡献源代码或文档并帮助创建了一款优秀软件的人... ?

如果您有任何评论、更正或添加,请随时联系Bodo Bauer,邮箱为bb@ricochet.net。我们将很乐意将它们添加到本文档中。

本文档的最新版本可在线获取,网址为https://www.kernel.org/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>或其包含的任何文件或子目录的打开文件描述符不会阻止<pid><pid>退出时被重新使用。对已死进程的打开/proc/<pid>文件描述符的操作通常会失败,并显示ESRCH。

表1-1:/proc中特定于进程的条目

文件 内容
clear_refs 清除在smaps输出中显示的页面引用位
cmdline 命令行参数
cpu 当前和最后执行它的CPU(2.4)(smp)
cwd 指向当前工作目录的链接
environ 环境变量的值
exe 指向此进程的可执行文件的链接
fd 包含所有文件描述符的目录
maps 可执行文件和库文件的内存映射(2.4)
mem 由此进程持有的内存
root 指向此进程的根目录的链接
stat 进程状态
statm 进程内存状态信息
status 以人类可读形式的进程状态
wchan 配置KALLSYMS=y时存在:显示任务所阻塞的内核函数符号 - 或者如果未阻塞则显示“0”
pagemap 页表
stack 报告完整的堆栈跟踪,通过CONFIG_STACKTRACE启用
smaps 基于maps的扩展,显示每个映射的内存消耗和相关标志
smaps_rollup 进程所有映射的累积smaps统计信息。这可以从smaps派生,但更快更方便
numa_maps 基于maps的扩展,显示每个映射的内存局部性和绑定策略以及每个映射的内存使用(以页为单位)

例如,要获取进程的状态信息,您只需读取文件/proc/PID/status

cat /proc/self/status

这将显示几乎与使用ps命令查看的信息相同。事实上,ps使用proc文件系统获取其信息。但是,通过读取文件/proc/PID/status,您可以更详细地查看进程。表1-2描述了它的字段。

statm文件包含有关进程内存使用情况的更详细信息。表1-3解释了它的七个字段。stat文件包含有关进程本身的详细信息。表1-4解释了它的字段。

(对于SMP CONFIG用户)

为了使会计可扩展,RSS相关信息以异步方式处理,值可能不是非常精确。要查看某一时刻的精确快照,您可以查看/proc/<pid>/smaps文件并扫描页表。这很慢,但非常精确。

表1-2:状态字段内容(截至4.19版本)

字段 内容
Name 可执行文件的文件名
Umask 文件模式创建掩码
State 状态(R表示运行,S表示睡眠,D表示在不可中断的等待中睡眠,Z表示僵尸,T表示被跟踪或停止)
Tgid 线程组ID
Ngid NUMA组ID(如果没有则为0)
Pid 进程ID
PPid 父进程的进程ID
TracerPid 跟踪此进程的进程的PID(如果没有则为0,或者跟踪器在当前PID命名空间之外)
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 驻留的共享内存大小(包括SysV shm、tmpfs映射和共享匿名映射)
VmData 私有数据段大小
VmStk 栈段大小
VmExe 文本段大小
VmLib 共享库代码大小
VmPTE 页表条目大小
VmSwap 匿名私有数据使用的交换量(不包括shmem交换使用量)
HugetlbPages 巨大页面内存部分大小
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 非自愿上下文切换次数

表1-3:statm字段内容(截至2.6.8-rc3版本)

字段 内容
size 程序总大小(页面)(与状态中的VmSize相同)
resident 内存部分的大小(页面)(与状态中的VmRSS相同)
shared 共享的页面数(即由文件支持,与状态中的RssFile+RssShmem相同)
trs “代码”页面数(不包括库;有问题,包括数据段)
lrs 库的页面数(2.6版本始终为0)
drs 数据/堆栈的页面数(包括库;有问题,包括库文本)
dt 脏页面数(2.6版本始终为0)

表1-4:stat字段内容(截至2.6.30-rc7版本)

字段 内容
pid 进程ID
tcomm 可执行文件的文件名
state 状态(R表示运行,S表示睡眠,D表示在不可中断的等待中睡眠,Z表示僵尸,T表示被跟踪或停止)
ppid 父进程的进程ID
pgrp 进程的进程组ID
sid 会话ID
tty_nr 进程使用的tty
tty_pgrp tty的进程组ID
flags 任务标志
min_flt 小错误次数
cmin_flt 子进程的小错误次数
maj_flt 大错误次数
cmaj_flt 子进程的大错误次数
utime 用户态jiffies
stime 内核态jiffies
cutime 子进程的用户态jiffies
cstime 子进程的内核态jiffies
priority 优先级级别
nice nice级别
num_threads 线程数
it_real_value (已过时,始终为0)
start_time 进程在系统启动后启动的时间
vsize 虚拟内存大小
rss 驻留集内存大小
rsslim 驻留集大小的当前限制(以字节为单位)
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 调度策略(参见sched_setscheduler手册)
blkio_ticks 等待块IO的时间
gtime 任务的guest时间(以jiffies为单位)
cgtime 任务子进程的guest时间(以jiffies为单位)
start_data 程序数据+BSS放置的地址上限
end_data 程序数据+BSS放置的地址下限
start_brk 程序堆可以使用brk()扩展的地址上限
arg_start 程序命令行放置的地址上限
arg_end 程序命令行放置的地址下限
env_start 程序环境放置的地址上限
env_end 程序环境放置的地址下限
exit_code 线程的退出码,以waitpid系统调用报告的形式显示

/proc/PID/maps文件包含当前映射的内存区域及其访问权限。

格式如下:

地址             权限  偏移  设备  节点号  路径名

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          [堆]
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          [栈]
ffffe000-fffff000 r-xp 00000000 00:00 0          [vdso]

其中,“地址”是进程中占用的地址空间,“权限”是一组权限:

r = 可读
w = 可写
x = 可执行
s = 共享
p = 私有(写时复制)

“偏移”是映射的偏移量,“设备”是设备(主:次),“节点号”是该设备上的索引节点。0表示内存区域未关联索引节点,如BSS(未初始化数据)的情况。 “路径名”显示了此映射关联文件的名称。如果映射未关联文件:

映射类型 描述
[堆] 程序的堆
[栈] 主进程的栈
[vdso] "虚拟动态共享对象",内核系统调用处理程序
[anon:<name>] 由用户空间命名的私有匿名映射
[anon_shmem:<name>] 由用户空间命名的匿名共享内存映射

如果是空,表示映射是匿名的
/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时分配的每个页面的大小(内核页大小),通常与页表项中的大小相同;支持VMA时MMU使用的页面大小(在大多数情况下与内核页大小相同);当前驻留在RAM中的映射的量(RSS);进程对此映射的比例份额(PSS);以及映射中干净和脏的共享和私有页面的数量。

进程的“proportional set size”(PSS)是它在内存中的页面数,其中每个页面由共享它的进程数除以。因此,如果一个进程有1000个页面是独占的,另外有1000个页面与另一个进程共享,它的PSS将是1500。“Pss_Dirty”是PSS中脏页面的部分。(“Pss_Clean”不包括在内,但可以通过从“Pss”中减去“Pss_Dirty”来计算。)

请注意,即使是MAP_SHARED映射的页面,但只有一个pte映射,即当前仅被一个进程使用的页面,也被视为私有而不是共享。

“Referenced”指示当前标记为已引用或已访问的内存量。

“Anonymous”显示不属于任何文件的内存量。即使与文件关联的映射可能包含匿名页面:当MAP_PRIVATE并且页面被修改时,文件页面将被私有匿名副本替换。

“KSM”报告有多少页面是KSM页面。请注意,KSM放置的零页不包括在内,只有实际的KSM页面。

“LazyFree”显示被madvise(MADV_FREE)标记的内存量。内存不会立即通过madvise()释放。在内存压力下,如果内存是干净的,它会被释放。请注意,由于当前实现中使用的优化,打印值可能低于实际值。如果这不是期望的行为,请提交错误报告。

“AnonHugePages”显示由透明巨大页支持的内存量。

“ShmemPmdMapped”显示由巨大页支持的共享(shmem/tmpfs)内存量。

“Shared_Hugetlb”和“Private_Hugetlb”显示由hugetlbfs页面支持的内存量,出于历史原因,这些内存量不包括在“RSS”或“PSS”字段中。这些也不包括在{共享,私有}_{干净,脏}字段中。

“Swap”显示了实际上会被匿名内存使用,但已经交换出去的内存量。

对于shmem映射,“Swap”还包括底层shmem对象的映射部分(并且没有被写时复制替换)已经交换出去的大小。“SwapPss”显示此映射的比例交换份额。与“交换”不同,这不考虑底层shmem对象的已交换出页面。“已锁定”指示映射是否在内存中被锁定。

“THPeligible”指示映射是否有资格分配THP页面以及THP是否PMD可映射 - 如果为真则为1,否则为0。它只显示当前状态。

"VmFlags"字段值值得单独描述。该成员以两个字母编码方式表示与特定虚拟内存区域相关的内核标志。以下是代码:

代码 描述
rd 可读
wr 可写
ex 可执行
sh 共享
mr 可读取(可能)
mw 可写入(可能)
me 可执行(可能)
ms 可共享(可能)
gd 栈段向下增长
pf 纯PFN范围
dw 禁止对映射文件进行写入
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跟踪
ss 影子栈页面

请注意,并不能保证每个标志和相关助记符都会出现在所有后续的内核版本中。事物会发生变化,标志可能会消失,或者相反,会添加新的标志。对它们含义的解释也可能会在未来发生变化。因此,使用这些标志的每个使用者都必须遵循每个特定内核版本的确切语义。

只有在启用了CONFIG_MMU内核配置选项时,才会存在此文件。

注意:读取/proc/PID/maps或/proc/PID/smaps在本质上是有竞争条件的(只有在单个读取调用中才能获得一致的输出)。

这通常在修改内存映射时进行这些文件的部分读取时会显现出来。尽管存在竞争条件,但我们提供以下保证:

  • 映射的地址永远不会向后移动,这意味着没有两个区域会重叠。

  • 如果在smaps/maps遍历的整个生命周期中给定的虚拟地址上有内容,那么就会有相应的输出。

/proc/PID/smaps_rollup文件包含与/proc/PID/smaps相同的字段,但它们的值是进程所有映射的相应值的总和。此外,它还包含以下字段:

  • Pss_Anon

  • Pss_File

  • Pss_Shmem

它们表示匿名、文件和共享内存页面的比例份额,如上面的smaps中所述。这些字段在smaps中被省略,因为每个映射都标识了它包含的所有页面的类型(anon、file或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找到页面映射的次数。有关详细说明,请参阅检查进程页表。

/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 == 节点0,N1 == 节点1,...)和支持映射的内核页面大小(以KB为单位)。

1.2 内核数据

与进程条目类似,内核数据文件提供有关运行中内核的信息。用于获取此信息的文件位于/proc目录中,并列在表1-5中。并非所有这些文件都会出现在您的系统中。这取决于内核配置和加载的模块,哪些文件存在,哪些文件缺失。

表1-5: Kernel info in /proc

文件 内容
apm 高级电源管理信息
buddyinfo 内核内存分配器信息(参见文本)(2.5)
bus 包含特定总线信息的目录
cmdline 内核命令行
cpuinfo CPU信息
devices 可用设备(块和字符设备)
dma 已使用的DMS通道
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 最近1、5和15分钟的平均负载;当前可运行的进程数(运行中或在就绪队列中);系统中的进程总数;最后创建的PID。所有字段由一个空格分隔,除了“当前可运行的进程数”和“系统中的进程总数”,它们由斜杠('/')分隔。示例:0.61 0.61 0.55 3/828 22084
locks 内核锁
meminfo 内存信息
misc 杂项
modules 已加载模块列表
mounts 挂载的文件系统
net 网络信息(参见文本)
pagetypeinfo 附加页面分配器信息(参见文本)(2.5)
partitions 系统已知分区表
pci PCI总线的已弃用信息(新方式->/proc/bus/pci/,由lspci解耦(2.4))
rtc 实时时钟
scsi SCSI信息(参见文本)
slabinfo Slab池信息
softirqs softirq使用情况
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  定时器
  1:        895          XT-PIC  键盘
  2:          0          XT-PIC  级联
  3:     531695          XT-PIC  aha152x
  4:    2014133          XT-PIC  串口
  5:      44401          XT-PIC  pcnet_cs
  8:          2          XT-PIC  实时时钟
 11:          8          XT-PIC  i82365
 12:     182918          XT-PIC  PS/2鼠标
 13:          1          XT-PIC  浮点单元
 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  定时器
  1:       8949       8958    IO-APIC-edge  键盘
  2:          0          0          XT-PIC  级联
  5:      11286      10161    IO-APIC-edge  声卡
  8:          1          0    IO-APIC-edge  实时时钟
  9:      27422      27407    IO-APIC-edge  3c503
 12:     113645     113873    IO-APIC-edge  PS/2鼠标
 13:          0          0          XT-PIC  浮点单元
 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的本地中断计数器。

ERR在IO-APIC总线上发生错误的情况下增加(IO-APIC连接SMP系统中的CPU的总线)。这意味着已检测到错误,IO-APIC会自动重试传输,所以这不应该是一个大问题,但您应该阅读SMP-FAQ。

2.6.2*中,/proc/interrupts再次扩展。这次的目标是让/proc/interrupts显示系统中使用的每个IRQ向量,而不仅仅是那些被认为是“最重要”的。新的向量有:

  • THR
    当机器检查阈值计数器(通常计算内存或缓存的ECC纠正错误)超过可配置的阈值时引发的中断。仅适用于某些系统。

  • TRM
    当CPU的温度超过阈值时,会发生热事件中断。当温度恢复正常时,也可能生成此中断。

  • SPU
    一种虚假中断是指在某个IO设备完全处理之前,由某个IO设备引发然后降低的某个中断。因此,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。/proc/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,因此缺少/proc/irq/[0-9]*目录。

在SMP系统上,节点文件显示了使用IRQ的设备所报告的节点。这些硬件本地化信息不包括任何可能的驱动程序本地化偏好信息。

prof_cpu_mask指定了系统范围性能分析器要分析的CPU。默认值是ffffffff(如果只有32个CPU,则表示所有CPU)。

IRQ的路由方式由IO-APIC处理,它在允许处理IRQ的所有CPU之间进行轮询。通常情况下,内核比用户拥有更多信息,因此默认设置对于几乎所有人来说都是最佳选择。[请注意,这仅适用于支持“轮询”中断分发的IO-APIC。]

/proc目录中还有三个重要的子目录:net、scsi和sys。一般规则是这些目录的内容或存在取决于内核配置。如果未启用SCSI,则scsi目录可能不存在。同样的情况也适用于net,只有在运行内核中存在网络支持时才会出现。

slabinfo文件提供了关于slab级别内存使用情况的信息。Linux在2.2版本以上使用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个20*PAGE_SIZE大小的页面块,ZONE_DMA中有4个21PAGE_SIZE大小的页面块,ZONE_NORMAL中有101个2^4PAGE_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()。一些“可回收”块也应该是可分配的,尽管可能需要回收大量的文件系统元数据才能实现这一点。

meminfo

提供有关内存分配和利用情况的信息。这取决于架构和编译选项。这里报告的一些计数器是重叠的。非重叠计数器报告的内存量可能不会加起来等于总体内存使用量,对于某些工作负载来说差异可能很大。在许多情况下,还有其他方法可以通过特定子系统的接口找出额外的内存使用情况,例如用于TCP内存分配的/proc/net/sockstat。

示例输出。您可能没有所有这些字段。

> 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
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
    可用总内存(即物理内存减去一些保留位和内核二进制代码)

  • MemFree
    总空闲内存。在高内存系统中,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
    映射到用户空间页表的非文件支持页面

  • Mapped
    已经进行了内存映射的文件,例如库文件

  • Shmem
    共享内存(shmem)和tmpfs使用的总内存

  • KReclaimable
    内核分配,内核在内存压力下将尝试回收。包括SReclaimable(下文)和其他使用shrinker进行直接分配的内容。

  • Slab
    内核数据结构缓存

  • SReclaimable
    Slab的一部分,可能会被回收,例如缓存

  • SUnreclaim
    Slab的一部分,在内存压力下无法被回收

  • KernelStack
    所有任务的内核堆栈消耗的内存

  • PageTables
    用户空间页表消耗的内存

  • SecPageTables
    用于次级页表的内存,目前包括x86和arm64上的KVM mmu分配

  • NFS_Unstable
    始终为零。之前已写入服务器但尚未提交到稳定存储的计数页面。

  • Bounce
    用于块设备“弹跳缓冲区”的内存

  • WritebackTmp
    FUSE用于临时写回缓冲区的内存

  • CommitLimit
    基于过度承诺比率('vm.overcommit_ratio'),这是当前系统上可分配的内存总量。只有在启用严格的过度承诺记账('vm.overcommit_memory'中的模式2)时才会遵守此限制。

    CommitLimit是使用以下公式计算的:

    CommitLimit =([总RAM页面] - [总巨大TLB页面])* 过度承诺比率/100 + [总交换页面]
    

    例如,在具有1G物理RAM和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
    通过早期内存测试识别为损坏的内存/内存量(以KB为单位)。如果未运行内存测试,则根本不会显示此字段。大小永远不会舍入为0KB。这意味着如果报告为0KB,则可以安全地假定至少进行了一次内存测试,而且没有一次测试发现了单个有缺陷的字节。

  • HardwareCorrupted
    内核识别为损坏的RAM/内存量(以KB为单位)。

  • AnonHugePages
    映射到用户空间页表的非文件支持的大页面

  • ShmemHugePages
    使用大页面分配的共享内存(shmem)和tmpfs使用的内存

  • ShmemPmdMapped
    使用大页面映射到用户空间的共享内存

  • FileHugePages
    使用大页面分配的文件系统数据(页面缓存)的内存

  • FilePmdMapped
    使用大页面映射到用户空间的页面缓存

  • CmaTotal
    为连续内存分配器(CMA)保留的内存

  • CmaFree
    CMA保留中剩余的空闲内存

  • HugePages_Total, HugePages_Free, HugePages_Rsvd, HugePages_Surp, Hugepagesize, Hugetlb
    请参阅HugeTLB页面。

  • DirectMap4k, DirectMap2M, DirectMap1G
    内核对RAM进行身份映射时使用的页表大小的详细信息。

vmallocinfo

提供关于vmalloced/vmaped区域的信息。每个区域一行,包含区域的虚拟地址范围、大小(以字节为单位)、创建者的调用者信息,以及根据区域类型的可选信息。

字段 描述
pages=nr 页的数量
phys=addr 如果指定了物理地址
ioremap I/O映射(ioremap()等)
vmalloc vmalloc()区域
vmap vmap()的页面
user VM_USERMAP区域
vpages 用于页指针的缓冲区被vmalloced(大页面)
N<node>=nr (仅在NUMA内核上)在内存节点<node>上分配的页面数
> 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已服务的softirq处理程序计数。

> 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遵循通常的模式。如果您配置内核以支持IP版本6,则表1-8显示了您可以获得的附加值。表1-9列出了文件及其含义。

表1-8: IPv6 info in /proc/net

文件 内容
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)

表1-9: Network info in /proc/net

文件 内容
arp 内核ARP表
dev 带有统计信息的网络设备
dev_mcast 设备正在监听的第二层多播组(接口索引、标签、引用数、绑定地址数)
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中显示的四个文件。

表1-10: Files in /proc/parport

文件 内容
autoprobe 已获取的任何IEEE-1284设备ID信息
devices 使用该端口的设备驱动程序列表。当前使用该端口的设备名称旁会出现+号(可能不会出现在任何设备旁)
hardware 并行端口的基地址、IRQ线和DMA通道
irq parport正在使用的IRQ。这是一个单独的文件,允许您通过写入新值(IRQ编号或无)来更改它。

1.6 /proc/tty中的TTY信息

您可以在/proc/tty目录中找到有关可用和实际使用的tty的信息。该目录中包含有关驱动程序和线路规则的条目,如表1-11所示。

表1-11:Files in /proc/tty

文件 内容
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:在用户模式下执行的被调整过优先级的进程

  • 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:运行被调整过优先级的虚拟机

"intr" 行给出了自启动以来服务的中断计数,对于可能的系统中断的每一个。第一列是所有服务中断的总数,包括未编号的特定体系结构中断;随后的每一列是特定编号中断的总数。未编号的中断不会显示,只会汇总到总数中。

"ctxt" 行给出了所有 CPU 上的上下文切换总数。

"btime" 行给出了系统启动的时间,以自 Unix 纪元以来的秒数表示。

"processes" 行给出了创建的进程和线程数,其中包括(但不限于)通过调用 fork() 和 clone() 系统调用创建的进程。

"procs_running" 行给出了正在运行或准备运行的线程总数(即可运行线程的总数)。

"procs_blocked" 行给出了当前被阻塞、等待 I/O 完成的进程数。

"softirq" 行给出了自启动以来服务的软中断计数,对于可能的系统软中断的每一个。第一列是所有服务的软中断的总数;随后的每一列是特定软中断的总数。

1.8 Ext4文件系统参数

您可以在/proc/fs/ext4中找到已挂载的ext4文件系统的信息。每个已挂载的文件系统都将在/proc/fs/ext4中以其设备名称(例如/proc/fs/ext4/hdc或/proc/fs/ext4/sda9或/proc/fs/ext4/dm-0)为基础拥有一个目录。每个设备目录中的文件如下表1-12所示。

表格1-12:Files in /proc/fs/ext4/<devname>

文件 内容
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 R = 可进行读操作
W = 可进行写操作
U = 可进行取消空白操作
flags E = 已启用
C = 优选控制台
B = 主引导控制台
p = 用于 printk 缓冲区
b = 不是TTY而是盲文设备
a = 在CPU离线时可以安全使用
major:minor 由冒号分隔的设备的主次编号

总结

/proc文件系统提供有关运行中系统的信息。它不仅允许访问进程数据,还允许通过读取层次结构中的文件来请求内核状态。

/proc的目录结构反映了各种信息的类型,并且使得查找特定数据变得简单,即使不是显而易见的地方。

第3章:每个进程的参数

3.1 /proc/<pid>/oom_adj/proc/<pid>/oom_score_adj- 调整oom-killer分数

这些文件可用于调整用于选择在内存不足(oom)条件下要终止的进程的不良启发式。

不良启发式为每个候选任务分配一个值,范围从0(永不终止)到1000(总是终止),以确定目标进程。单位大致上是允许内存范围内的比例,该进程可以根据其当前内存和交换使用的估计来分配。例如,如果任务使用了所有允许的内存,其不良分数将为1000。如果它使用了其允许内存的一半,其分数将为500。

“允许”的内存量取决于调用oom killer的上下文。如果是由于分配任务的cpuset的内存耗尽,允许的内存表示分配给该cpuset的内存集。如果是由于mempolicy的节点耗尽,允许的内存表示mempolicy节点的集合。如果是由于达到内存限制(或交换限制),允许的内存就是配置的限制。最后,如果是由于整个系统内存不足,允许的内存表示所有可分配的资源。

在使用不良分数确定要终止的任务之前,将 /proc/<pid>/oom_score_adj 的值添加到不良分数中。可接受的值范围从-1000(OOM_SCORE_ADJ_MIN)到+1000(OOM_SCORE_ADJ_MAX)。这允许用户空间通过始终偏好某个任务或完全禁用oom终止来极化oom终止的偏好。最低可能的值-1000 相当于完全禁用该任务的oom终止,因为它将始终报告0的不良分数。

因此,用户空间很容易定义要考虑的每个任务的内存量。例如,设置 /proc/<pid>/oom_score_adj 值为+500 大致相当于允许共享相同系统、cpuset、mempolicy 或内存控制器资源的其余任务使用至少多出50%的内存。另一方面,-500 的值大致相当于将任务允许的内存减少50%。

为了向后兼容以前的内核,也可以使用 /proc/<pid>/oom_adj 来调整不良分数。其可接受的值范围从-16(OOM_ADJUST_MIN)到+15(OOM_ADJUST_MAX),特殊值-17(OOM_DISABLE)用于完全禁用该任务的oom终止。其值与 /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的影响(读取可能已经从页面缓存中满足)。

  • wchar
    I/O 计数:写入的字符
    这个任务导致或将导致写入磁盘的字节数。这里也适用类似的警告,就像 rchar 一样。

  • syscr
    I/O 计数:读取系统调用
    尝试计算读取I/O操作的次数,即像 read() 和 pread() 这样的系统调用。

  • syscw
    I/O 计数:写入系统调用
    尝试计算写入I/O操作的次数,即像 write() 和 pwrite() 这样的系统调用。

  • read_bytes
    I/O 计数:读取的字节数
    尝试计算该进程实际导致从存储层获取的字节数。在 submit_bio() 级别完成,因此对于基于块的文件系统是准确的。 <请稍后添加关于NFS和CIFS的状态>

  • write_bytes
    I/O 计数:写入的字节数
    尝试计算该进程导致发送到存储层的字节数。这是在页面脏时完成的。

  • cancelled_write_bytes
    这里的主要不准确性在于截断。如果一个进程向文件写入1MB,然后删除该文件,实际上不会执行任何写出。但它将被记录为已经导致了1MB的写入。换句话说:这个进程导致的未发生的字节数,通过截断页面缓存。一个任务也可以导致“负”IO。如果这个任务截断了一些脏的页面缓存,另一个任务已经被记录为(在其 write_bytes 中)的一些IO将不会发生。我们可以从截断任务的 write_bytes 中减去这些,但这样做会导致信息丢失。

注意
在当前的实现状态下,在32位机器上这有点竞争:如果进程A读取进程B的 /proc/pid/io,而进程B正在更新其中的一个64位计数器,进程A可能会看到一个中间结果。

有关更多信息,请参阅 Documentation/accounting 中的 taskstats 文档。

3.4 /proc/<pid>/coredump_filter - 核心转储过滤设置

当一个进程被转储时,只要核心文件的大小没有限制,所有匿名内存都将被写入核心文件。但有时我们不想转储一些内存段,例如巨大的共享内存或DAX。相反,有时我们希望将文件支持的内存段保存到核心文件中,而不仅仅是单独的文件。

/proc/<pid>/coredump_filter 允许您自定义在转储 <pid> 进程时将转储哪些内存段。coredump_filter 是内存类型的位掩码。如果位掩码的某一位被设置,将转储相应内存类型的内存段,否则它们不会被转储。

支持以下9种内存类型:

  • (位 0)匿名私有内存

  • (位 1)匿名共享内存

  • (位 2)文件支持的私有内存

  • (位 3)文件支持的共享内存

  • (位 4)文件支持的私有内存区域中的ELF头页面(仅在位 2 被清除时有效)

  • (位 5)巨大页面私有内存

  • (位 6)巨大页面共享内存

  • (位 7)DAX私有内存

  • (位 8)DAX共享内存

    请注意,像帧缓冲区这样的MMIO页面永远不会被转储,而vDSO页面无论位掩码状态如何都会被转储。

    请注意,位 0-4 不影响巨大页面或DAX内存。巨大页面内存仅受位 5-6 的影响,而DAX仅受位 7-8 的影响。

coredump_filter 的默认值为 0x33;这意味着所有匿名内存段、ELF头页面和巨大页面私有内存都将被转储。

如果不想转储附加到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)   挂载ID:挂载的唯一标识符(在卸载后可能会被重用)
(2)   父ID:父级的ID(对于挂载树顶部的自身)
(3)   主:次:文件系统上文件的 st_dev 值
(4)   根目录:文件系统内的挂载根目录
(5)   挂载点:相对于进程根目录的挂载点
(6)   挂载选项:每个挂载的选项
(n…m) 可选字段:零个或多个“tag[:value]”形式的字段
(m+1) 分隔符:标记可选字段的结束
(m+2) 文件系统类型:形式为“type[.subtype]”的文件系统名称
(m+3) 挂载源:文件系统特定信息或“none”
(m+4) 超级块选项:每个超级块的选项

解析器应忽略所有未识别的可选字段。目前可能的可选字段有:

字段 描述
shared:X 在对等组 X 中共享挂载
master:X 挂载作为对等组 X 的从属
propagate_from:X 挂载作为从属,并从对等组 X 接收传播[1]
unbindable 挂载不可解绑

[1]: X 是进程根目录下最近的主导对等组。如果 X 是挂载的直接主组,或者在同一根目录下没有主导对等组,则只会出现 "master:X" 字段,而不会出现 "propagate_from:X" 字段。

有关挂载传播的更多信息,请参阅:

共享子树 (Shared Subtrees)

3.6 /proc/<pid>/comm & /proc/<pid>/task/<tid>/comm - 任务的 comm 值

这些文件提供了一种访问任务的 comm 值的方法。它还允许任务设置自己或其一个线程兄弟的 comm 值。与 cmdline 值相比,comm 值的大小受到限制,因此写入长度超过内核的 TASK_COMM_LEN(当前为 16 个字符)的内容将导致截断的 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' 是事件掩码的十六进制形式,'ignored_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

当启用 CONFIG_PROC_PID_ARCH_STATUS 时,该文件显示了任务的体系结构特定状态。对于 x86 架构的特定条目,有一个名为 AVX512_elapsed_ms 的条目。

  • 如果机器支持 AVX512,则该条目显示自上次记录 AVX512 使用以来经过的毫秒数。记录是在任务被调度出时尽力而为地进行的。这意味着该值取决于两个因素:

    1. 任务在 CPU 上运行而没有被调度出所花费的时间。使用 CPU 隔离和单个可运行任务时,这可能需要几秒钟。
    2. 任务上次被调度出以来的时间。根据被调度出的原因(时间片耗尽、系统调用等),这可能是任意长的时间。

    因此,该值不能被视为精确和权威的信息。使用该信息的应用程序必须意识到系统的整体情况,以确定任务是否真正使用了 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' 成员中,以便快速访问。

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() /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