最权威的解释肯定是man手册了,Linux系统proc目录的man手册地址:https://linux.die.net/man/5/proc。虽然和Android有一些出入,但是很大一部分是一样的,具有参考性。
1. /proc目录
首先来介绍一下/proc目录,它是一个虚拟的目录,其下面的文件和目录也都是虚拟的,不占用实际的存储空间,而是存在于系统内存中。proc以文件系统的方式为访问系统内核的操作提供接口,它是动态从系统内核中读出所需信息的。
- /proc/cmdline:显示内核启动的命令行。
- /proc/cpuinfo:显示系统cpu的信息。
- /proc/filesystems,显示当前注册了的文件系统列表,nodev表示为虚拟文件系统。
- /proc/interrupts:显示当前系统的中断信息.
- /proc/ioports:被占用的输入/输出地址范围列表。
- /proc/kmsg:输出内核消息日志。
- /proc/loadavg:监控cpu平均负载,其数值为所有核上cpu占用的累加值,前三个分别表示最近1、5、15分钟的平均负载,第四个表示当前运行进程数和进程总数,最后一个表示最近运行的进程id。
- /proc/locks:打开文件上的加锁信息。
- /proc/meminfo:显示物理及虚拟内存使用情况。
- /proc/misc:内核函数misc_register登记的设备驱动程序。
- /proc/modules:加载的内核模块列表。
- Proc/mounts:当前系统所安装的文件系统信息(包括手动安装的)。
- /proc/stat:系统简要信息。
- /proc/uptime:分别表示系统启动时间和系统空闲时间。
- /proc/version:系统内核版本。
- /proc/net:其实际挂载点是/proc/self/net,能够显示当前各种网络情况,例如通过tcp文件可以查看tcp连接数及连接情况。
- /proc/sys 报告各种不同的内核参数,某些参数能在root的情况下进行修改。
- /proc/devices 当前挂载的所有软硬件设备(字符设备和块设备),包括主设备号和设备名称。
- /proc/asound:声卡相关的信息。
- /proc/buddyinfo:每个内存区中每个order有多少块可用,和内存碎片问题有关。
- /proc/bus:输入设备信息。
- /proc/cgroups:查看cgroups子系统信息。
- /proc/diskstats:用于显示磁盘、分区和统计信息。
- /proc/execdomains:安全相关的信息。
- /proc/fb:帧缓冲设备信息。
- /proc/iomem:记录物理地址的分配情况。
- /proc/kallsyms:内核符号表信息。
- /proc/pagetypeinfo:内存分页信息。
- /proc/partitions:分区信息
- /proc/sched_debug:cpu调度信息。
- /proc/softirqs:软中断情况。
- /proc/vmallocinfo:vmalloc内存分配信息。
- /proc/vmstat:统计虚拟内存信息。
- /proc/pid:显示进城相关的所有信息。
可以说系统的几乎所有信息都可以在/proc目录中找到。
2. /proc/XXX/进程目录
在/proc目录下面还有很多目录的名字是数字,这些目录保存了当前系统中运行的所有进程的信息,数字对应的是进程的pid。
$ ls -d /proc/[0-9]*
/proc/1/ /proc/302/ /proc/451/ /proc/496/ /proc/556/ /proc/633/
/proc/127/ /proc/317/ /proc/452/ /proc/497/ /proc/557/ /proc/718/
/proc/2/ /proc/339/ /proc/453/ /proc/5/ /proc/558/ /proc/755/
/proc/250/ /proc/385/ /proc/454/ /proc/501/ /proc/559/ /proc/760/
/proc/260/ /proc/4/ /proc/455/ /proc/504/ /proc/565/ /proc/761/
/proc/275/ /proc/402/ /proc/463/ /proc/505/ /proc/569/ /proc/9884/
/proc/290/ /proc/433/ /proc/487/ /proc/509/ /proc/594/ /proc/774/
/proc/3/ /proc/450/ /proc/491/ /proc/554/ /proc/595/
# ls -l 9884/
dr-xr-xr-x shell shell 2016-10-19 15:51 attr
-r-------- shell shell 0 2016-10-19 15:51 auxv
-r--r--r-- shell shell 0 2016-10-19 15:51 cgroup
--w------- shell shell 0 2016-10-19 15:51 clear_refs
-r--r--r-- shell shell 0 2016-10-18 17:19 cmdline
-rw-r--r-- shell shell 0 2016-10-19 15:51 comm
-rw-r--r-- shell shell 0 2016-10-19 15:51 coredump_filter
lrwxrwxrwx shell shell 2016-10-19 15:51 cwd -> /
-r-------- shell shell 0 2016-10-19 15:51 environ
lrwxrwxrwx shell shell 2016-10-18 18:55 exe -> /system/bin/adb
dr-x------ shell shell 2016-10-19 15:51 fd
dr-x------ shell shell 2016-10-19 15:51 fdinfo
-r--r--r-- shell shell 0 2016-10-19 15:51 limits
-rw-r--r-- shell shell 0 2016-10-19 15:51 loginuid
-r--r--r-- shell shell 0 2016-10-19 15:51 maps
-rw------- shell shell 0 2016-10-19 15:51 mem
-r--r--r-- shell shell 0 2016-10-19 15:51 mountinfo
-r--r--r-- shell shell 0 2016-10-19 15:51 mounts
-r-------- shell shell 0 2016-10-19 15:51 mountstats
dr-xr-xr-x shell shell 2016-10-19 15:51 net
dr-x--x--x shell shell 2016-10-19 15:51 ns
-rw-r--r-- shell shell 0 2016-10-19 15:51 oom_adj
-r--r--r-- shell shell 0 2016-10-19 15:51 oom_score
-rw-r--r-- shell shell 0 2016-10-19 15:51 oom_score_adj
-r--r--r-- shell shell 0 2016-10-19 15:51 pagemap
-r--r--r-- shell shell 0 2016-10-19 15:51 personality
lrwxrwxrwx shell shell 2016-10-19 15:51 root -> /
-r--r--r-- shell shell 0 2016-10-19 15:51 schedstat
-r--r--r-- shell shell 0 2016-10-19 15:51 sessionid
-r--r--r-- shell shell 0 2016-10-19 15:51 smaps
-r--r--r-- shell shell 0 2016-10-19 15:51 stack
-r--r--r-- shell shell 0 2016-10-18 17:19 stat
-r--r--r-- shell shell 0 2016-10-19 15:51 statm
-r--r--r-- shell shell 0 2016-10-18 21:42 status
dr-xr-xr-x shell shell 2016-10-18 18:58 task
-r--r--r-- shell shell 0 2016-10-19 15:51 wchan
- cmdline:该(虚拟)文件包含了启动该进程的整个命令行。它未曾格式化:程序与其参数之间没有空格,行末也没有换行。
- cwd:该符号链接指向该进程的当前工作目录。现在我见过的基本都是根目录,从上面的输出就能看出它链接到的是根目录。
- environ:该文件包含为该进程定义的所有环境变量,格式为 变量=值。与 cmdline 文件一样,其内容未曾格式化过:各个变量之间没有分行,文件末尾也没有换行。
- exe:这是指向该进程所执行的可执行程序文件的符号链接。上面的输出可以看出链接到/system/bin/adb,一般的用户进程是链接到/system/bin/app_process,这是zygote进程的实际实现文件,因为所有进程都是zygote孵化出来的,所以这里都会链接到它。
- fd:在此子目录中包含了该进程当前打开的所有描述符。下面看一下进程9884的输出:
实际上,这是该进程打开的文件描述符列表,每个描述符由一个符号链接表示,其名称为该描述符的编号,并指向该描述符打开的文件。注意这些符号链接的权限:它们的意义仅代表被相应描述符打开的文件的权限。root@hammerhead:/proc/9884 # ls -l fd/ lr-x------ shell shell 2016-10-19 16:41 0 -> /dev/null l-wx------ shell shell 2016-10-19 16:41 1 -> /dev/null lrwx------ shell shell 2016-10-19 16:41 11 -> socket:[421052] l-wx------ shell shell 2016-10-19 16:41 2 -> /dev/null lrwx------ shell shell 2016-10-19 16:41 3 -> socket:[448153] lrwx------ shell shell 2016-10-19 16:41 4 -> socket:[448154] lrwx------ shell shell 2016-10-19 16:41 5 -> socket:[449926] lrwx------ shell shell 2016-10-19 16:41 6 -> socket:[449927] lrwx------ shell shell 2016-10-19 16:41 7 -> socket:[449928] lr-x------ shell shell 2016-10-19 16:41 9 -> /dev/__properties__
- maps:这个文件中显示了该进程的虚拟地址空间的分布情况。该文件有6列,自左至右各列为:
地址:库在进程里地址范围权限:虚拟内存的权限,r=读,w=写,x=,s=共享,p=私有;偏移量:库在进程里地址范围设备:映像文件的主设备号和次设备号,当设备号为 0 且没有 inode 号或文件名时,它就是一个匿名映射,表示没有节点与内存相对应;节点:映像文件的节点号;路径: 映像文件的路径每项都与一个vm_area_struct结构成员对应。
示例:
root@hammerhead:/proc/9884 # cat maps b6bb6000-b6bb8000 rw-p 00000000 00:00 0 b6cb8000-b6cb9000 ---p 00000000 00:00 0 b6cb9000-b6db6000 rw-p 00000000 00:00 0 [stack:9885] b6db6000-b6dd6000 r--s 00000000 00:0b 6245 /dev/__properties__ b6dd6000-b6dee000 r-xp 00000000 b3:19 949 /system/lib/libm.so b6dee000-b6def000 r--p 00017000 b3:19 949 /system/lib/libm.so b6def000-b6df0000 rw-p 00018000 b3:19 949 /system/lib/libm.so b6df0000-b6df1000 r-xp 00000000 b3:19 1065 /system/lib/libstdc++.so b6df1000-b6df2000 r--p 00000000 b3:19 1065 /system/lib/libstdc++.so b6df2000-b6df3000 rw-p 00001000 b3:19 1065 /system/lib/libstdc++.so b6df3000-b6e3a000 r-xp 00000000 b3:19 827 /system/lib/libc.so b6e3a000-b6e3b000 ---p 00000000 00:00 0 b6e3b000-b6e3d000 r--p 00047000 b3:19 827 /system/lib/libc.so b6e3d000-b6e40000 rw-p 00049000 b3:19 827 /system/lib/libc.so b6e40000-b6e4e000 rw-p 00000000 00:00 0 b6e4e000-b6f25000 r-xp 00000000 b3:19 849 /system/lib/libcrypto.so b6f25000-b6f26000 ---p 00000000 00:00 0 b6f26000-b6f32000 r--p 000d7000 b3:19 849 /system/lib/libcrypto.so b6f32000-b6f38000 rw-p 000e3000 b3:19 849 /system/lib/libcrypto.so b6f38000-b6f3a000 rw-p 00000000 00:00 0 b6f3a000-b6f3c000 r--p 00000000 00:00 0 b6f3c000-b6f3e000 rw-p 00000000 00:00 0 b6f3e000-b6f4d000 r-xp 00000000 b3:19 176 /system/bin/linker b6f4d000-b6f4e000 r--p 0000e000 b3:19 176 /system/bin/linker b6f4e000-b6f4f000 rw-p 0000f000 b3:19 176 /system/bin/linker b6f4f000-b6f50000 rw-p 00000000 00:00 0 b6f50000-b6f6a000 r-xp 00000000 b3:19 113 /system/bin/adb b6f6a000-b6f6b000 r--p 00019000 b3:19 113 /system/bin/adb b6f6b000-b6f6c000 rw-p 0001a000 b3:19 113 /system/bin/adb b6f6c000-b6f7d000 rw-p 00000000 00:00 0 b7041000-b7044000 rw-p 00000000 00:00 0 [heap] bebcc000-bebed000 rw-p 00000000 00:00 0 [stack] ffff0000-ffff1000 r-xp 00000000 00:00 0 [vectors]
按照上面的介绍可以很容易理解每个字段的意义。有两点需要说明:1. b6f38000-b6f3a000 rw-p 00000000 00:00 0,具有rw-p权限,并且后面的设备号路径都是0的,是堆空间。
2. 为什么每个so都出现三次,看它们的权限就明白了,r-xp是代码段,r--p是只读数据段,rw-p是读写数据段。
- root:该符号链接指向该进程使用的根目录。通常为 /。
- stat: 包含了进程的众多信息和与CPU相关的信息,所有值都是从系统启动开始累计到当前时刻的。
root@hammerhead:/proc/9884 # cat stat 9884 (adb) S 1 9882 5801 0 -1 1077936128 304 0 2 0 125 378 0 0 20 0 2 0 2477313 3063808 220 4294967295 3069509632 3069614751 3200174704 3200165768 3068212952 0 0 4096 42232 4294967295 0 0 17 0 0 0 0 0 0 3069619180 3069621324 3070496768
解释:pid=9884 进程(包括轻量级进程,即线程)号
comm=adb 应用程序或命令的名字
task_state=S 任务的状态,R:runnign, S:sleeping (TASK_INTERRUPTIBLE), D:disk sleep (TASK_UNINTERRUPTIBLE), T: stopped, T:tracing stop,Z:zombie, X:dead
ppid=1 父进程ID
pgid=9882 线程组号
sid=5801 c该任务所在的会话组ID
后面字段与我在网上查到的不一样,这里就暂时先不列出来了,等后续我查清楚了再列出来。
- statm: 包含了进程的内存页面相关的信息。
解释:root@hammerhead:/proc/9884 # cat statm 748 220 169 26 0 333 0
size(pages):任务虚拟地址空间大小,VmSize/4
Resident(pages):正在使用的物理内存大小,VmRSS/4
Shared(pages):共享页数
Trs(pages):程序所拥有的可执行虚拟内存大小, VmExe/4
Lrs(pages):被映像倒任务的虚拟内存空间的库的大小,VmLib/4
Drs(pages):程序数据段和用户态的栈的大小,(VmData+ VmStk )/4
dt(pages):脏页数量
- status:该文件包含该进程的众多信息:可执行文件名、当前状态、PID 和 PPID、实际及有效的 UID 和 GID、内存使用情况、以及其他。请注意,stat 和 statm 现已过时。它们包含的信息现存于 status。
root@hammerhead:/proc/9884 # cat status Name: adb State: S (sleeping) Tgid: 9884 Pid: 9884 PPid: 1 TracerPid: 0 Uid: 2000 2000 2000 2000 Gid: 2000 2000 2000 2000 FDSize: 32 Groups: 1003 1004 1007 1011 1015 1028 3001 3002 3003 3006 VmPeak: 4012 kB VmSize: 2992 kB VmLck: 0 kB VmPin: 0 kB VmHWM: 880 kB VmRSS: 880 kB VmData: 1196 kB VmStk: 136 kB VmExe: 104 kB VmLib: 1304 kB VmPTE: 8 kB VmSwap: 0 kB Threads: 2 SigQ: 1/12274 SigPnd: 0000000000000000 ShdPnd: 0000000000000000 SigBlk: 0000000000000000 SigIgn: 0000000000001000 SigCgt: 000000000000a4f8 CapInh: 0000000000000000 CapPrm: 0000000000000000 CapEff: 0000000000000000 CapBnd: fffffff0000000c0 Cpus_allowed: f Cpus_allowed_list: 0-3 voluntary_ctxt_switches: 7 nonvoluntary_ctxt_switches: 46
解释:Name 应用程序或命令的名字
State 任务的状态,运行/睡眠/僵死/
SleepAVG 任务的平均等待时间(以nanosecond为单位),交互式任务因为休眠次数多、时间长,它们的 sleep_avg 也会相应地更大一些,所以计算出来的优先级也会相应高一些。
Tgid 线程组号
Pid 任务ID
Ppid 父进程ID
TracerPid 接收跟踪该进程信息的进程的ID号
Uid Uid euid suid fsuid
Gid Gid egid sgid fsgid
FDSize 文件描述符的最大个数,file->fds
Groups
VmSize(KB) 任务虚拟地址空间的大小 (total_vm-reserved_vm),其中total_vm为进程的地址空间的大小,reserved_vm:进程在预留或特殊的内存间的物理页
VmLck(KB) 任务已经锁住的物理内存的大小。锁住的物理内存不能交换到硬盘 (locked_vm)
VmRSS(KB) 应用程序正在使用的物理内存的大小,就是用ps命令的参数rss的值 (rss)
VmData(KB) 程序数据段的大小(所占虚拟内存的大小),存放初始化了的数据; (total_vm-shared_vm-stack_vm)
VmStk(KB) 任务在用户态的栈的大小 (stack_vm)
VmExe(KB) 程序所拥有的可执行虚拟内存的大小,代码段,不包括任务使用的库 (end_code-start_code)
VmLib(KB) 被映像到任务的虚拟内存空间的库的大小 (exec_lib)
VmPTE 该进程的所有页表的大小,单位:kb
Threads 共享使用该信号描述符的任务的个数,在POSIX多线程序应用程序中,线程组中的所有线程使用同一个信号描述符。
SigQ 待处理信号的个数
SigPnd 屏蔽位,存储了该线程的待处理信号
ShdPnd 屏蔽位,存储了该线程组的待处理信号
SigBlk 存放被阻塞的信号
SigIgn 存放被忽略的信号
SigCgt 存放被俘获到的信号
CapInh Inheritable,能被当前进程执行的程序的继承的能力
CapPrm Permitted,进程能够使用的能力,可以包含CapEff中没有的能力,这些能力是被进程自己临时放弃的,CapEff是CapPrm的一个子集,进程放弃没有必要的能力有利于提高安全性
CapEff Effective,进程的有效能力
CapBnd:是系统的边界能力,我们无法改变它。
Cpus_allowed:f指出该进程可以使用CPU的亲和性掩码,因为我们指定为4块CPU,所以这里就是F(1111)。Cpus_allowed_list:0-3指出该进程可以使用CPU的列表,这里是0-3。voluntary_ctxt_switches表示进程主动切换的次数.nonvoluntary_ctxt_switches表示进程被动切换的次数.
- mem:这是一个很重要的虚拟文件,它可以用来访问该进程的内存页面,你可以通过open、read、lseek函数来访问里面的内容。如果你用cat来打印里面的内容是会出错的。这个文件的主要用途我觉得是其它进程如果想要访问这个进程内存的话,就需要通过对它的读取了。
另外/proc/9884/下还有很多其它的文件和目录,后续会慢慢补齐。