1. 概念:
proc 文件系统是由内核创建的虚拟文件系统,被内核用来向外界报告信息的一个文件系统,存储着当前内核运行状态的一系列特殊文件,是在系统运行时才创建的,所以它仅存在于内存之中而不在外存(硬盘、flash)上。通过proc虚拟文件可以实现Linux内核空间和用户间之间进行通信,它是内核提供给我们的查询中心,可以通过它查看系统硬件及当前运行的进程信息,甚至可以通过修改其中的某些文件改变内核的运行状态。
Linux中许多工具的数据来源正是proc目录中的内容,比如lsmod的命令是cat /proc/modules的别名。为了查看及使用上的方便,proc里的文件通常会按照相关性进行分类存储于不同的目录甚至子目录中,如/proc/scsi目录中存储的就是当前系统上所有SCSI设备的相关信息,/proc/N中存储的则是系统当前正在运行的进程的相关信息,其中N为正在运行的进程(可以想象得到,在某进程结束后其相关目录则会消失)。
大多数虚拟文件可以使用文件查看命令如cat、more或者less进行查看,有些文件信息表述的内容可以一目了然,但也有文件的信息却不怎么具有可读性。不过,这些可读性较差的文件在使用一些命令如apm、free、lspci或top查看时却可以有着不错的表现。
2. 分类:
2.1. /proc/pid_num/
这些数字代表的是系统当前运行进程的进程号,每个数字目录中都有对应该进程的相关信息。
2.1.1. ./statm
当运行cat /proc/1/statm时会打印出7组数字,每一个数字的单位都是页,而不同数字代表的含义则有很大区别:
size:任务虚拟地址空间大小
Resident:正在使用的物理内存大小
Shared:共享页数
Trs:程序所拥有的可执行虚拟内存大小
Lrs:被映像倒任务的虚拟内存空间的库的大小
Drs:程序数据段和用户态的栈的大小
dt:脏页数量
2.1.2. ./cmdline
包含了该进程的启动命令(绝对路径)
2.1.3. ./mem
不可读,此文件代表进程占用内存
2.1.4. ./cwd
链接到此进程的工作目录
2.1.5. ./environ
此文件包含进程环境变量列表
2.1.6. ./comm
包含进程名
2.1.7. ./coredump_filter
程序崩溃或使用了gcore工具生成进程core文件时,可以通过设定内核转存掩码来筛选需要dump的部分内存。
而此文件则代表coredump过滤的类型,支持以下其中内存:
(bit 0) anonymous private memory(匿名私有内存段)
(bit 1) anonymous shared memory(匿名共享内存段)
(bit 2) file-backed private memory(file-backed 私有内存段):文件映射的内存
(bit 3) file-backed shared memory(file-bakced 共享内存段)
(bit 4) ELF header pages in file-backed private memory areas (it is
effective only if the bit 2 is cleared)(ELF 文件映射,只有在bit 2 复位的时候才起作用)
(bit 5) hugetlb private memory(大页面私有内存) :mmap 映射的MAP_HUGETLB类型数据
(bit 6) hugetlb shared memory(大页面共享内存)
可以通过修改文件/proc//coredump_filter来筛选需要dump的内存段。
/proc//coredump_filter中的值为16进制,默认值为0x23,转化为二进制:00100011,从右向左看,bit 0、bit 1、bit 5 被置位,也就是说会转储所有的匿名内存段和大页面私有内存段。
2.1.8. ./exe
这是个链接(可执行文件),可以链接到进程的可执行文件
2.1.9. ./fd
此目录包含进程所有相关的文件描述符,进入目录后可以看到很多链接。
linux中, 每一个进程在内核中,都对应有一个“打开文件”数组,存放指向文件对象的指针,而 fd 是这个数组的下标。
我们对文件进行操作时,系统调用,将fd传入内核,内核通过fd找到文件,对文件进行操作。
既然是数组下标,fd的类型为int, < 0 为非法值, >=0 为合法值。在linux中,一个进程默认可以打开的文件数为1024个,fd的范围为0~1023。可以通过设置,改变最大值。
在linux中,值为0、1、2的fd,分别代表标准输入、标准输出、标准错误输出。在上一篇文章中,使用重定向 2>/dev/null 就是把标准错误输出重定向到位桶中去,不显示出来。因为 0 1 2已经被linux使用了,通常在程序中打开的fd,是从3开始的。但我们在判断一个fd是否合法时,依然要使用>=0的判断标准。
fd的分配原则,是从小到大,找到第一个不用的进行分配。
除了open之外, socket编程的socket()/accept()等函数,也会返回一个fd值。
1)Linux系统下,所有进程允许打开的最大fd数量。查询语句:
/proc/sys/fs/file-max
2)Linux系统下,所有进程已经打开的fd数量及允许的最大数量。查询语句:
/proc/sys/fs/file-nr
3)单个进程允许打开的最大fd数量.查询语句:
ulimit -n
4)单个进程(例如进程id为5454)已经打开的fd.查询语句:
ls -l /proc/5454/fd/
当ls -ls后,可以看到每个链接的含义,比如
0 lrwx------ 1 root root 64 May 15 09:50 3 ->> socket:[2374]
fd为3的代表socket产生的文件描述符。
2.1.10. ./fdinfo
此目录存放着每个文件描述符的相关信息
2.1.11. ./limits
此文件包含了进程所限制的一些参数
2.1.12. ./maps
此文件包含当前映射的内存区域
2.1.13. ./moutinfo
此进程相关的挂在信息
2.1.14. ./mounts
现在的 Linux 系统里一般都有这么三个文件:/etc/fstab,/etc/mtab,和 /proc/mounts,比较容易让人迷惑。简单解释一下。
/etc/fstab 是只读不写的,它提供的是系统上挂载设备的静态信息,比如 mount -a 就会挂载 /etc/fstab 里面指定的文件系统。
/etc/mtab 是供 mount/umount 进行读写的,是相对动态的。读的话,比如你在挂载一个文件系统时缺少一个参数,它就会自动去/etc/mtab 或者 /etc/fstab 里去查,如果找到的话,只要一个参数也够。写的话,比如你umount了一个文件系统,umount 就会删掉/etc/mtab 里面的相关记录。
看似上面的这两个文件已经够用了,但是新的情况出现了。Linux 内核引入了一个 mount namespace,是给container用的。因为这个的出现,Linux 不得不引入 /proc/mounts。为什么呢?因为记录 mount 信息的 /etc/mtab 是全局的,也就是说,就算你的某个进程有自己的 namespace,但只要还和外面共享同一个 /etc/mtab,那么,里面进行umount/mount操作的信息也会被记录到/etc/mtab里,外面也会看到!凌乱了!由此可见,我们不能有全局的mtab,肿么办呢?/proc/mounts 出来了,有人可能觉得它也是全局的啊!可你仔细看一下的话会发现,它其实是到 /proc/self/mounts 的一个符号链接!如此以来,container 里面的 /proc/mounts 和外面的当然就不会一样了!聪明啊!
所以,/etc/mtab 已经过时了,应该被抛弃,或者直接符号链接到/proc/mounts。同理,查看系统上挂载的文件系统的话,直接调用无参数的mount也是不妥的,因为那样也是读 /etc/mtab。我们应该使用 util-linux-ng 提供的一个新命令: findmnt,它是读的 /proc/self/mountinfo。
2.1.15. ./mountstate
包含进程挂载状态
2.1.16. ./net/
2.1.16.1. ./arp
arp信息,表,统计
2.1.16.2. ./dev
设备信息,类似于ifconfig的网络设备统计
2.1.16.3. ./dev_mcast
组播包统计
2.1.16.4. ./igmp
IGMP分组情况
2.1.16.5. ./netlink
netlink套接口信息
2.1.16.6. ./netstat
网络流量的多种统计
2.1.16.7. ./raw
原始套接口的套接口表
2.1.16.8. ./rout
静态路由
2.1.16.9. ./rt_cache # 在此目录下 # ip route show cache
路由缓存表
2.1.16.10. ./snmp
协议统计
2.1.16.11. ./sockestat
使用的tcp/udp/raw/pac/syc_cookies的数量
2.1.16.12. ./tcp
TCP连接的套接口
2.1.16.13. ./udp
同上
2.1.16.14. ./unix
UNIX域套接口的套接表
2.1.17. ./ns
包含进程所属的各个namespace的文件描述符
2.1.18. ./oom*
oom_adj/oom_score:这两个与linux的OOM机制有关的文件(关于OOM请看这里),oom_adj相当于一个因子,它值越大,在OOM时更容易被系统kill掉,但最终决定是否被kill的是oom_score,其实计算这个oom_score时,就是根据oom_adj来的,oom_adj更大,计算出来的oom_score就更大,也能容易在OOM时被系统kill掉。当然如果是很重要的服务现场,为了避免出现这种情况设置oom_adj=0就行,表示永远不会因为OOM被kill。
2.1.19. ./personality
?????????????????????
2.1.20. ./root
指向当前进程运行根目录的符号链接,通常就是“/”;在Unix和Linux系统上,通常采用chroot命令使每个进程运行于独立的根目录
2.1.21. ./stat
此文件就是将后面的status进行简写,只提供数据,减少篇幅,方便查看。每一个数据都可以在status中找到对应属性
2.1.22. ./statm
查看进程所占用内存
第二列为Resident(pages)—— 应用程序正在使用的物理内存的大小 VmRSS/4,为实际使用内存数值的四分之一。
2.1.23. ./status
查看进程相关状态
2.1.24. ./task
第二列为Resident(pages)—— 应用程序正在使用的物理内存的大小 VmRSS/4,为实际使用内存数值的四分之一。
2.1.25. ./wchan
??????????
2.2. /proc/apm/
高级电源管理(APM)版本信息及电池相关状态信息,通常由apm命令使用;
2.3. ./buddyinfo
是linuxbuddy系统管理物理内存的debug信息。
在linux中使用buddy算法解决物理内存的外碎片问题,其把所有空闲的内存,以2的幂次方的形式,分成11个块链表,分别对应为1、2、4、8、16、32、64、128、256、512、1024个页块。
而Linux支持NUMA技术,对于NUMA设备,NUMA系统的结点通常是由一组CPU和本地内存组成,每一个节点都有相应的本地内存,因此buddyinfo 中的Node0表示节点ID;而每一个节点下的内存设备,又可以划分为多个内存区域(zone),因此下面的显示中,对于Node0的内存,又划分类DMA、Normal、HighMem区域。而后面则是表示空闲的区域。
此处以Normal区域进行分析,第二列值为100,表示当前系统中normal区域,可用的连续两页的内存大小为1002PAGE_SIZE;第三列值为52,表示当前系统中normal区域,可用的连续四页的内存大小为522^2PAGE_SIZE
2.4. ./cmdline
在启动时传递至内核的相关参数信息,这些信息通常由lilo或grub等启动管理工具进行传递;
2.5. ./consoles
当前终端的信息
2.6. ./cpuinfo
存储了处理器的相关信息
2.7. ./crypto
系统已安装的密码算法及相关信息
2.8. ./devices
系统已经加载的所有块设备和字符设备的信息,包含主设备号和设备组(与主设备号对应的设备类型)名
2.9. ./diskstats
每块磁盘设备的磁盘I/O统计信息列表;(内核2.5.69以后的版本支持此功能)
2.10. ./filesystems
当前被内核支持的文件系统类型列表文件,被标示为nodev的文件系统表示不需要块设备的支持;通常mount一个设备时,如果没有指定文件系统类型将通过此文件来决定其所需文件系统的类型;
2.11. ./interrupts
X86或X86_64体系架构系统上每个IRQ相关的中断号列表;多路处理器平台上每个CPU对于每个I/O设备均有自己的中断号;
2.12. ./iomem
每个物理设备上的记忆体(RAM或者ROM)在系统内存中的映射信息
2.13. ./ioports
当前正在使用且已经注册过的与物理设备进行通讯的输入-输出端口范围信息列表;如下面所示,第一列表示注册的I/O端口范围,其后表示相关的设备
2.14. ./loadavg
保存关于CPU和磁盘I/O的负载平均值,其前三列分别表示每1秒钟、每5秒钟及每15秒的负载平均值,类似于uptime命令输出的相关信息;第四列是由斜线隔开的两个数值,前者表示当前正由内核调度的实体(进程和线程)的数目,后者表示系统当前存活的内核调度实体的数目;第五列表示此文件被查看前最近一个由内核创建的进程的PID
2.15. ./locks
保存当前由内核锁定的文件的相关信息,包含内核内部的调试数据;每个锁定占据一行,且具有一个惟一的编号;如下输出信息中每行的第二列表示当前锁定使用的锁定类别,POSIX表示目前较新类型的文件锁,由lockf系统调用产生,FLOCK是传统的UNIX文件锁,由flock系统调用产生;第三列也通常由两种类型,ADVISORY表示不允许其他用户锁定此文件,但允许读取,MANDATORY表示此文件锁定期间不允许其他用户任何形式的访问
2.16. ./meminfo
系统中关于当前内存的利用状况等的信息,常由free命令使用;可以使用文件查看命令直接读取此文件,其内容显示为两列,前者为统计属性,后者为对应的值
2.17. ./mounts
在内核2.4.29版本以前,此文件的内容为系统当前挂载的所有文件系统,在2.4.19以后的内核中引进了每个进程使用独立挂载名称空间的方式,此文件则随之变成了指向/proc/self/mounts(每个进程自身挂载名称空间中的所有挂载点列表)文件的符号链接;/proc/self是一个独特的目录,后文中会对此目录进行介绍;
第一列表示挂载的设备,第二列表示在当前目录树中的挂载点,第三点表示当前文件系统的类型,第四列表示挂载属性(ro或者rw),第五列和第六列用来匹配/etc/mtab文件中的转储(dump)属性
2.18. ./modules
当前装入内核的所有模块名称列表,可以由lsmod命令使用,也可以直接查看;如下所示,其中第一列表示模块名,第二列表示此模块占用内存空间大小,第三列表示此模块有多少实例被装入,第四列表示此模块依赖于其它哪些模块,第五列表示此模块的装载状态(Live:已经装入;Loading:正在装入;Unloading:正在卸载),第六列表示此模块在内核内存(kernel memory)中的偏移量
2.19. ./partitions
块设备每个分区的主设备号(major)和次设备号(minor)等信息,同时包括每个分区所包含的块(block)数目
2.20. ./pci
内核初始化时发现的所有PCI设备及其配置信息列表,其配置信息多为某PCI设备相关IRQ信息,可读性不高,可以用“/sbin/lspci –vb”命令获得较易理解的相关信息;在2.6内核以后,此文件已为/proc/bus/pci目录及其下的文件代替
2.21. ./slabinfo
在内核中频繁使用的对象(如inode、dentry等)都有自己的cache,即slab pool,而/proc/slabinfo文件列出了这些对象相关slap的信息;详情可以参见内核文档中slapinfo的手册页
2.22. ./stat
实时追踪自系统上次启动以来的多种统计信息;如下所示,其中,
“cpu”行后的八个值分别表示以1/100(jiffies)秒为单位的统计值(包括系统运行于用户模式、低优先级用户模式,运系统模式、空闲模式、I/O等待模式的时间等);
“intr”行给出中断的信息,第一个为自系统启动以来,发生的所有的中断的次数;然后每个数对应一个特定的中断自系统启动以来所发生的次数;
“ctxt”给出了自系统启动以来CPU发生的上下文交换的次数。
“btime”给出了从系统启动到现在为止的时间,单位为秒;
“processes (total_forks) 自系统启动以来所创建的任务的个数目;
“procs_running”:当前运行队列的任务的数目;
“procs_blocked”:当前被阻塞的任务的数目;
2.23. ./swaps
当前系统上的交换分区及其空间利用信息,如果有多个交换分区的话,则会每个交换分区的信息分别存储于/proc/swap目录中的单独文件中,而其优先级数字越低,被使用到的可能性越大;下面是作者系统中只有一个交换分区时的输出信息
2.24. ./uptime
系统上次启动以来的运行时间,如下所示,其第一个数字表示系统运行时间,第二个数字表示系统空闲时间,单位是秒
2.25. ./version
当前系统运行的内核版本号,包括gcc版本。
2.26. ./vmstat
当前系统虚拟内存的多种统计数据,信息量可能会比较大,这因系统而有所不同,可读性较好;下面为作者机器上输出信息的一个片段;(2.6以后的内核支持此文件)
2.27. ./zoneinfo
内存区域(zone)的详细信息列表,信息量较大,下面列出的是一个输出片段:
2.28. ./sys
与 /proc下其它文件的“只读”属性不同的是,管理员可对/proc/sys子目录中的许多文件内容进行修改以更改内核的运行特性,事先可以使用“ls -l”命令查看某文件是否“可写入”。写入操作通常使用类似于“echo DATA > /path/to/your/filename”的格式进行。需要注意的是,即使文件可写,其一般也不可以使用编辑器进行编辑。
2.29. ./debug
?????????
2.30. ./dev
为系统上特殊设备提供参数信息文件的目录,其不同设备的信息文件分别存储于不同的子目录中,如大多数系统上都会具有的/proc/sys/dev /cdrom和/proc/sys/dev/raid(如果内核编译时开启了支持raid的功能) 目录,其内存储的通常是系统上cdrom和raid的相关参数信息文件。