/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 使用以来经过的毫秒数。记录是在任务被调度出时尽力而为地进行的。这意味着该值取决于两个因素:
- 任务在 CPU 上运行而没有被调度出所花费的时间。使用 CPU 隔离和单个可运行任务时,这可能需要几秒钟。
- 任务上次被调度出以来的时间。根据被调度出的原因(时间片耗尽、系统调用等),这可能是任意长的时间。
- 因此,该值不能被视为精确和权威的信息。使用该信息的应用程序必须意识到系统的整体情况,以确定任务是否真正使用了 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