linux基础-proc详解

摘要

Linux系统下/proc/目录详解

/proc/下部分文件目录详解

本文仅挑几个可能用的上的记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
.
|-- cgroups # 资源隔离
|-- cmdline # 这个文件给出了内核启动的命令行。它和用于进程的cmdline项非常相似。
|-- cpuinfo # 这个文件提供了有关系统CPU的多种信息。这些信息是从内核里对CPU的测试代码中得到的。
|-- devices # 这个文件列出字符和块设备的主设备号,以及分配到这些设备号的设备名称。
|-- filesystems # 这个文件列出可供使用的文件系统类型,一种类型一行。虽然它们通常是编入内核的文件系统类型,但该文件还可以包含可加载的内核模块加入的其它文件系统类型。
|-- kcore # 这个文件是系统的物理内存以core文件格式保存的文件。例如,GDB能用它考察内核的数据结构。它不是纯文本,而是/proc目录下为数不多的几个二进制格式的项之一。
|-- loadavg # 这个文件给出以几个不同的时间间隔计算的系统平均负载,这就如同uptime命令显示的结果那样。前三个数字是平均负载。这是通过计算过去1分钟,5分钟,15分钟里运行队列中的平均任务数得到的。随后是正在运行的任务数和总任务数。最后是上次使用的进程号。
|-- meminfo # 这个文件给出了内存状态的信息。它显示出系统中空闲内存,已用物理内存和交换内存的总量。它还显示出内核使用的共享内存和缓冲区总量。这些信息的格式和free命令显示的结果类似。
|-- modules # 这个文件给出可加载内核模块的信息。lsmod程序用这些信息显示有关模块的名称,大小,使用数目方面的信息。
|-- mounts -> self/mounts # 这个文件以/etc/mtab文件的格式给出当前系统所安装的文件系统信息。这个文件也能反映出任何手工安装从而在/etc/mtab文件中没有包含的文件系统。
|-- net -> self/net # 此目录下的文件描述或修改了联网代码的行为。可以通过使用arp,netstat,route和ipfwadm命令设置或查询这些特殊文件中的许多文件。
|-- stat # 这个文件包含的信息有CPU利用率,磁盘,内存页,内存对换,全部中断,接触开关以及赏赐自举时间(自1970年1月1日起的秒数)。
|-- swaps
|-- sys # 内核参数相关
|-- sysvipc
|-- uptime # 这个文件给出自从上次系统自举以来的秒数,以及其中有多少秒处于空闲。这主要供uptime程序使用。比较这两个数字能够告诉你长期来看CPU周期浪费的比例。
|-- version # 这个文件只有一行内容,说明正在运行的内核版本。可以用标准的编程方法进行分析获得所需的系统信息。
|-- vmstat # vmstat 命令信息来源之一 https://www.cnblogs.com/ftl1012/p/vmstat.html
`-- zoneinfo

/proc/net子目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
arp	#转储每个网络接口的arp表中dev包的统计
dev #来自网络设备的统计
dev_mcast #列出二层(数据链路层)多播组
igmp #加入的IGMP多播组
netlink #netlink套接口的信息
netstat #网络流量的多种统计。第一行是信息头,带有每个变量的名称。接下来的一行保存相应变量的值
raw #原始套接口的套接口表
route #静态路由表
rpc #包含RPC信息的目录
rt_cache #路由缓冲
snmp #snmp agent的ip/icmp/tcp/udp协议统计;各行交替给出字段名和值
sockstat #列出使用的tcp/udp/raw/pac/syc_cookies的数量
tcp #TCP连接的套接口
udp #UDP连接的套接口表
unix #UNIX域套接口的套接口表

/proc/<pid>/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
.
|-- cgroup # 资源隔离
|-- cmdline # 包含进程的完整命令行信息。如果这个进程是zombie进程,则这个文件没有任何内容。
|-- cwd -> /home/work/opbin/domain-router # 当前工作目录的软链接
|-- comm # 进程名
|-- environ # 进程的环境变量
|-- exe -> /home/work/opbin/domain-router/sbin/nginx # 实际运行程序的软链接
|-- fd # 包含进程打开文件的情况
|-- fdinfo
|-- io # 进程的io信息
|-- limits # 进程的资源限制
|-- maps # 进程的内存区域映射信息
|-- mountinfo
|-- mounts
|-- mountstats
|-- net # 进程使用的网络内核参数
|-- root -> / # 是进程根目录的软链接
|-- sched
|-- smaps
|-- stack # 显示当前进程的内核调用栈信息,只有内核编译时打开了CONFIG_STACKTRACE编译选项,才会生成这个文件
|-- stat # 包含了所有CPU活跃的信息,该文件中的所有值都是从系统启动开始累计到当前时刻
|-- statm # 显示进程所占用内存大小的统计信息,包含七个值,度量单位是page(page大小可通过getconf PAGESIZE得到)
|-- status # 进程内存信息
|-- syscall # 显示当前进程正在执行的系统调用
|-- task # 进程包含的的线程信息
`-- wchan # 显示当进程sleep时,kernel当前运行的函数

statm

/proc/[pid]/statm显示进程所占用内存大小的统计信息,包含七个值,度量单位是page(page大小可通过getconf PAGESIZE得到)。举例如下:

1
2
# cat /proc/2948/statm  
72362 12945 4876 569 0 24665 0
  • 进程占用的总的内存
  • 进程当前时刻占用的物理内存
  • 同其它进程共享的内存
  • 进程的代码段
  • 共享库(从2.6版本起,这个值为0)
  • 进程的堆栈
  • dirty pages(从2.6版本起,这个值为0)。

/proc/6873/stat

1
19211 (docker-proxy) S 18582 18582 18582 0 -1 1077936384 400 0 24 0 385 870 0 0 20 0 5 0 1476270373 111624192 397 18446744073709551615 94908437864448 94908439349548 140733819451920 140733819451256 94908438772659 0 2079996453 0 2143420159 0 0 0 17 0 0 0 16 0 0 94908441446824 94908442361816 94908444303360 140733819457191 140733819457307 140733819457307 140733819457506 0

每个参数意思为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
参数 解释
pid=19211 进程(包括轻量级进程,即线程)号
comm=docker-proxy 应用程序或命令的名字
task_state=R 任务的状态,R:runnign, S:sleeping (TASK_INTERRUPTIBLE), D:disk sleep (TASK_UNINTERRUPTIBLE), T: stopped, T:tracing stop,Z:zombie, X:dead
ppid=6723 父进程ID
pgid=6873 线程组号
sid=6723 c该任务所在的会话组ID
tty_nr=34819(pts/3) 该任务的tty终端的设备号,INT(34817/256)=主设备号,(34817-主设备号)=次设备号
tty_pgrp=6873 终端的进程组号,当前运行在该任务所在终端的前台任务(包括shell 应用程序)的PID。
task->flags=8388608 进程标志位,查看该任务的特性
min_flt=77 该任务不需要从硬盘拷数据而发生的缺页(次缺页)的次数
cmin_flt=0 累计的该任务的所有的waited-for进程曾经发生的次缺页的次数目
maj_flt=0 该任务需要从硬盘拷数据而发生的缺页(主缺页)的次数
cmaj_flt=0 累计的该任务的所有的waited-for进程曾经发生的主缺页的次数目
utime=1587 该任务在用户态运行的时间,单位为jiffies
stime=1 该任务在核心态运行的时间,单位为jiffies
cutime=0 累计的该任务的所有的waited-for进程曾经在用户态运行的时间,单位为jiffies
cstime=0 累计的该任务的所有的waited-for进程曾经在核心态运行的时间,单位为jiffies
priority=25 任务的动态优先级
nice=0 任务的静态优先级
num_threads=3 该任务所在的线程组里线程的个数
it_real_value=0 由于计时间隔导致的下一个 SIGALRM 发送进程的时延,以 jiffy 为单位.
start_time=5882654 该任务启动的时间,单位为jiffies
vsize=1409024(page) 该任务的虚拟地址空间大小
rss=56(page) 该任务当前驻留物理地址空间的大小
Number of pages the process has in real memory,minu 3 for administrative purpose.
这些页可能用于代码,数据和栈。
rlim=4294967295(bytes) 该任务能驻留物理地址空间的最大值
start_code=134512640 该任务在虚拟地址空间的代码段的起始地址
end_code=134513720 该任务在虚拟地址空间的代码段的结束地址
start_stack=3215579040 该任务在虚拟地址空间的栈的结束地址
kstkesp=0 esp(32 位堆栈指针) 的当前值, 与在进程的内核堆栈页得到的一致.
kstkeip=2097798 指向将要执行的指令的指针, EIP(32 位指令指针)的当前值.
pendingsig=0 待处理信号的位图,记录发送给进程的普通信号
block_sig=0 阻塞信号的位图
sigign=0 忽略的信号的位图
sigcatch=082985 被俘获的信号的位图
wchan=0 如果该进程是睡眠状态,该值给出调度的调用点
nswap 被swapped的页数,当前没用
cnswap 所有子进程被swapped的页数的和,当前没用
exit_signal=17 该进程结束时,向父进程所发送的信号
task_cpu(task)=0 运行在哪个CPU上
task_rt_priority=0 实时进程的相对优先级别
task_policy=0 进程的调度策略,0=非实时进程,1=FIFO实时进程;2=RR实时进程

/proc/pid/status

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
Name:	dockerd	# 进程名
State: S (sleeping) # 进程状态
## R (running)", "S (sleeping)", "D (disk sleep)", "T (stopped)", "T(tracing stop)", "Z (zombie)", or "X (dead)"
Tgid: 18582 # 线程组的ID,一个线程一定属于一个线程组(进程组)
Ngid: 0
Pid: 18582 # 进程的ID,更准确的说应该是线程的ID
PPid: 1 # 当前进程的父进程ID
TracerPid: 0 # 跟踪当前进程的进程ID,如果是0,表示没有跟踪,例如用strace跟踪
Uid: 0 0 0 0
Gid: 0 0 0 0
# 第一列数字(RUID):实际用户ID,指的是进程执行者是谁.
# 第二列数字(EUID):有效用户ID,指进程执行时对文件的访问权限.
# 第三列数字(SUID):保存设置用户ID,作为effective user ID的副本,在执行exec调用时后能重新恢复原来的effectiv user ID.
# 第四列数字(FSUID):目前进程的文件系统的用户识别码.一般情况下,文件系统的用户识别码(fsuid)与有效的用户识别码(euid)是相同的.
# RUID和EUID是由启动进程的用户决定的
# EUID,如果程序设定了setuid,那么在程序运行时是用程序的owner权限来运行程序,而不是启动的用户权限
终端1)
FDSize: 128 # FDSize是当前分配的文件描述符,这个值不是当前进程使用文件描述符的上限.
# 而如果超过32个文件描述符,将以32进行递增,如果是64位系统,将以64进行递增.
# FDSize这个值不会减少,如果我们程序打开了300个文件,并不会因为关闭文件,而减少FDSize这个值.
Groups: # 这里的groups表示启动这个进程的用户所在的组.
NStgid: 18582
NSpid: 18582
NSpgid: 18582
NSsid: 18582
VmPeak: 581816 kB # 当前进程运行过程中占用内存的峰值
VmSize: 581752 kB # 进程现在正在占用的内存
VmLck: 0 kB # 进程已经锁住的物理内存的大小.锁住的物理内存不能交换到硬盘
VmPin: 0 kB
VmHWM: 89832 kB # 得到分配到物理内存的峰值
VmRSS: 40128 kB # 现在使用的物理内存
VmData: 476676 kB # 进程数据段的大小
VmStk: 132 kB # 进程堆栈段的大小.
VmExe: 47116 kB # 进程代码的大小
VmLib: 6128 kB # 进程所使用LIB库的大小
VmPTE: 396 kB # 占用的页表的大小.
VmPMD: 24 kB
VmSwap: 0 kB # 进程占用Swap的大小.
HugetlbPages: 0 kB
Threads: 12 # 表示当前进程组有12个线程.
SigQ: 0/7338 # 当前待处理信号的个数
SigPnd: 0000000000000000 # 屏蔽位,存储了该线程的待处理信号,等同于线程的PENDING信号
ShdPnd: 0000000000000000 # 屏蔽位,存储了该线程组的待处理信号.等同于进程组的PENDING信号
SigBlk: 0000000000000000 # 存放被阻塞的信号,等同于BLOCKED信号
SigIgn: 0000000000000000 # 存放被忽略的信号,等同于IGNORED信号
SigCgt: ffffffffffc1feff # 存放捕获的信号,等同于CAUGHT信号
CapInh: 0000000000000000 # 表示能够被当前进程执行的程序继承的能力
CapPrm: 0000003fffffffff # 表示进程能够使用的能力,在cap_permitted中可以包含cap_effective中没有的能力,这些能力是被进程自己临时放弃的,也可以说cap_effective是cap_permitted的一个子集
CapEff: 0000003fffffffff # 当一个进程要进行某个特权操作时,操作系统会检查cap_effective的对应位是否有效,而不再是检查进程的有效UID是否为0
CapBnd: 0000003fffffffff # 是系统的边界能力,我们无法改变它
CapAmb: 0000000000000000
Seccomp: 0
Cpus_allowed: 1 # 指出该进程可以使用CPU的亲和性掩码,因为我们指定为两块CPU,所以这里就是3,如果该进程指定为4个CPU(如果有话),这里就是F(1111)
Cpus_allowed_list: 0 # 0-1指出该进程可以使用CPU的列表,这里是0-1
Mems_allowed: 00000000,00000001 # 通cpu
Mems_allowed_list: 0 # 通cpu,使用了结点0的内存资源
voluntary_ctxt_switches: 24243383 # 表示进程主动切换的次数.
nonvoluntary_ctxt_switches: 6102321 # 表示进程被动切换的次数

通过stat计算cpu使用率

  • ps命令算出来的cpu使用率相对于进程启动时的平均值,随着进程运行时间的增大,该值会趋向于平缓。
  • 某一个线程在其运行期间其所使用的cpu可能会发生变化。
  • 在多核的情况下top命令输出的cpu使用率实质是按cpu个数*100%计算的。

/proc/cpuinfo

通过该文件根据processor出现的次数统计cpu的逻辑个数(包括多核、超线程)。

/proc/stat

1
2
3
4
5
6
7
8
9
cpu  16382797 158616 10937579 2903612556 18440580 0 465274 0 0 0
cpu0 16382797 158616 10937579 2903612556 18440580 0 465274 0 0 0
intr 4393119213 23 10 0 0 94 0 3 0 0 0 0 0 15 0 28917959 0 0 0 0 0 0 0 0 0 0 50063236 0 175989464 2840 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 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ctxt 10253696983
btime 1520949357
processes 23321669
procs_running 1
procs_blocked 0
softirq 2567139785 1 1177546622 7 351246654 14459636 0 16 0 0 1023886849

第一行的数值表示的是CPU总的使用情况,所以我们只要用第一行的数字计算就可以了。下表解析第一行各数值的含义:

jiffies是内核中的一个全局变量,用来记录自系统启动一来产生的节拍数,在linux中,一个节拍大致可理解为操作系统进程调度的最小时间片,不同linux内核可能值有不同,通常在1ms到10ms之间

参数 解析(单位:jiffies)
user (16382797) 从系统启动开始累计到当前时刻,处于用户态的运行时间,不包含 nice值为负进程
nice (158616) 从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间
system (10937579) 从系统启动开始累计到当前时刻,处于核心态的运行时间
idle (2903612556) 从系统启动开始累计到当前时刻,除IO等待时间以外的其它等待时间iowait (18440580) 从系统启动开始累计到当前时刻,IO等待时间(since 2.5.41)
irq (0) 从系统启动开始累计到当前时刻,硬中断时间(since 2.6.0-test4)
softirq (465274) 从系统启动开始累计到当前时刻,软中断时间stealstolen(0),guest(0)

总的cpu时间:totalCpuTime = user + nice + system + idle + iowait + irq + softirq + stealstolen + guest

/proc/<pid>/stat

以下只解释对我们计算Cpu使用率有用相关参数

参数 解释
pid=6873 进程号
utime=1587 该任务在用户态运行的时间,单位为jiffies
stime=41958 该任务在核心态运行的时间,单位为jiffies
cutime=0 所有已死线程在用户态运行的时间,单位为jiffies
cstime=0 所有已死在核心态运行的时间,单位为jiffies

进程的总Cpu时间: processCpuTime = utime + stime + cutime + cstime,该值包括其所有线程的cpu时间。

/proc/<pid>/task/<tid>/stat

该文件的内容格式以及各字段的含义同/proc/<pid>/stat文件。

注意,该文件中的tid字段表示的不再是进程号,而是linux中的轻量级进程(lwp),即我们通常所说的线程。

线程Cpu时间: threadCpuTime = utime + stime

总的Cpu使用率计算

  • 需要采样两个足够短的时间间隔的cpu快照与进程快照分别记作t1,t2
    • user、nice、system、idle、iowait、irq、softirq、stealstolen、guest
  • 计算总的Cpu时间片 totalCpuTime
    • 把第一次的所有cpu使用情况求和,得到s1
    • 把第二次的所有cpu使用情况求和,得到s2
    • s2 - s1得到这个时间间隔内的所有时间片,即 totalCpuTime = s2 - s1
  • 计算空闲时间idle
    • idle(第四列的数据)=用第二次的第四列 - 第一次的第四列即可
  • 计算cpu使用率
    • pcpu =100* (total-idle)/total

某一进程Cpu使用率的计算

  • 采样两个足够短的时间间隔的cpu快照与进程快照
  • 每一个进程快照均为 (utime、stime、cutime、cstime)的4元组
  • 计算总cpu时间片 totalCpuTime1、totalCpuTime2
  • 计算总进程cpu时间片 processCpuTime1、processCpuTime2
  • 计算该进程的cpu使用率
    • pcpu = 100*( processCpuTime2 – processCpuTime1) / (totalCpuTime2 – totalCpuTime1)
    • 如果是多核情况下还需乘以cpu的个数;

某一线程Cpu使用率的计算

  • 采样两个足够短的时间隔的cpu快照与线程快照
  • 每一个线程快照均为 (utime、stime)的2元组
  • 计算总cpu时间片 totalCpuTime1、totalCpuTime2
  • 计算总进程cpu时间片 threadCpuTime1、threadCpuTime2
  • 计算该线程的cpu使用
    • pcpu = 100*( threadCpuTime2 – threadCpuTime1) / (totalCpuTime2 – totalCpuTime1)
    • 如果是多核情况下还需乘以cpu的个数