proc - 进程信息伪文件系统
Posted fanweisheng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了proc - 进程信息伪文件系统相关的知识,希望对你有一定的参考价值。
描述
/proc 是一个伪文件系统, 被用作内核数据结构的接口, 而不仅仅是解释说明 /dev/kmem. /proc里的大多数文件都是只读的, 但也可以通过写一些文件来改变内核变量.
下面对整个 /proc 目录作一个大略的介绍.
- [number]
- 在 /proc 目录里, 每个正在运行的进程都有一个以该进程 ID 命名的子目录, 其下包括如下的目录和伪文件.
- cmdline
- 该文件保存了进程的完整命令行. 如果该进程已经被交换出内存, 或者该进程已经僵死, 那么就没有任何东西在该文件里, 这时候对该文件的读操作将返回零个字符. 该文件以空字符 null 而不是换行符作为结束标志.
- cwd
- 一个符号连接, 指向进程当前的工作目录. 例如, 要找出进程 20 的 cwd, 你可以:
cd /proc/20/cwd; /bin/pwd
请注意 pwd 命令通常是 shell 内置的, 在这样的情况下可能工作得不是很好.
- environ
- 该文件保存进程的环境变量, 各项之间以空字符分隔, 结尾也可能是一个空字符. 因此, 如果要输出进程 1 的环境变量, 你应该:
(cat /proc/1/environ; echo) | tr ";\000"; ";\n";
(至于为什么想要这么做, 请参阅 lilo(8).)
- exe
- 也是一个符号连接, 指向被执行的二进制代码.
在 Linux 2.0 或者更早的版本下, 对 exe 特殊文件的 readlink(2) 返回一个如下格式的字符串:
[设备号]:节点号
举个例子, [0301]:1502 就是某设备的 1502 节点, 该设备的主设备号为 03 (如 IDE, MFM 等驱动器), 从设备号为 01 (第一个驱动器的第一分区).
而在 Linux 2.2 下, readlink(2) 则给出命令的实际路径名.
另外, 该符号连接也可以正常析引用(试图打开 exe 文件实际上将打开一个可执行文件). 你甚至可以键入 /proc/[number]/exe 来运行 [number] 进程的副本.
带 -inum 选项的 find(1) 命令可以定位该文件.
- fd
- 进程所打开的每个文件都有一个符号连接在该子目录里, 以文件描述符命名, 这个名字实际上是指向真正的文件的符号连接,(和 exe 记录一样).例如, 0 是标准输入, 1 是标准输出, 2 是标准错误, 等等.
程序有时可能想要读取一个文件却不想要标准输入,或者想写到一个文件却不想将输出送到标准输出去,那么就可以很有效地用如下的办法骗过(假定 -i 是输入文件的标志, 而 -o 是输出文件的标志):
foobar -i /proc/self/fd/0 -o /proc/self/fd/1 ...
这样就是一个能运转的过滤器. 请注意该方法不能用来在文件里搜索, 这是因为 fd 目录里的文件是不可搜索的.在 UNIX 类的系统下, /proc/self/fd/N 基本上就与 /dev/fd/N 相同. 实际上, 大多数的 Linux MAKEDEV 脚本都将 /dev/fd 符号连接到 [..]/proc/self/fd 上.
- maps
- 该文件包含当前的映象内存区及他们的访问许可.
格式如下:
address perms offset dev inode 00000000-0002f000 r-x-- 00000400 03:03 1401 0002f000-00032000 rwx-p 0002f400 03:03 1401 00032000-0005b000 rwx-p 00000000 00:00 0 60000000-60098000 rwx-p 00000400 03:03 215 60098000-600c7000 rwx-p 00000000 00:00 0 bfffa000-c0000000 rwx-p 00000000 00:00 0
address 是进程所占据的地址空间, perms 是权限集:
r = read w = write x = execute s = shared p = private (copy on write)
offset 是文件或者别的什么的偏移量, dev 是设备号(主设备号:从设备号), 而 inode 则是设备的节点号. 0 表明没有节点与内存相对应, 就象 bss 的情形.
在 Linux 2.2 下还增加了一个域给可用的路径名.
- mem
- 该文件并不是 mem (1:1) 设备, 尽管它们有相同的设备号. /dev/mem 设备是做任何地址转换之前的物理内存, 而这里的 mem 文件是访问它的进程的内存.目前这个 mem 还不能 mmap(2) (内存映射)出去,而且可能一直要等到内核中增加了一个通用的 mmap(2) 以后才能实现. (也许在你读本手册页时这一切已经发生了)
- mmap
- mmap(2) 做的 maps 映射目录,是和 exe, fd/* 等类似的符号连接. 请注意 maps 包含了比 /proc/*/mmap 更多的信息, 所以应该废弃 mmap.
";0"; 通常指 libc.so.4.
在 linux 内核 1.1.40 里, /proc/*/mmap 被取消了. (现在是 真的 废弃不用了!)
- root
- 依靠系统调用 chroot(2), unix 和 linux 可以让每个进程有各自的文件系统根目录. 由 chroot(2) 系统调用设置.根指向文件系统的根,性质就象 exe, fd/* 等一样.
- stat
- 进程状态信息, 被命令 ps(1) 使用.
现将该文件里各域, 以及他们的 scanf(3) 格式说明符, 按顺序分述如下:
- pid %d
- 进程标识.
- comm %s
- 可执行文件的文件名, 包括路径. 该文件是否可见取决于该文件是否已被交换出内存.
- state %c
- ";RSDZT"; 中的一个, R 是正在运行, S 是在可中断的就绪态中睡眠, D 是在不可中断的等待或交换态中睡眠, Z 是僵死, T 是被跟踪或被停止(由于收到信号).
- ppid %d
- 父进程 PID.
- pgrp %d
- 进程的进程组 ID.
- session %d
- 进程的会话 ID.
- tty %d
- 进程所使用终端.
- tpgid %d
- 当前拥有该进程所连接终端的进程所在的进程组 ID.
- flags %u
- 进程标志. 目前每个标志都设了数学位, 所以输出里就不包括该位. crt0.s 检查数学仿真这可能是一个臭虫, 因为不是每个进程都是用 c 编译的程序. 数学位应该是十进制的 4, 而跟踪位应该是十进制的 10.
- minflt %u
- 进程所导致的小错误(minor faults)数目, 这样的小错误(minor faults)不需要从磁盘重新载入一个内存页.
- cminflt %u
- 进程及其子进程所导致的小错误(minor faults)数目.
- majflt %u
- 进程所导致的大错误(major faults)数目, 这样的大错误(major faults)需要重新载入内存页.
- cmajflt %u
- 进程及其子进程所导致的大错误(major faults)数目.
- utime %d
- 进程被调度进用户态的时间(以 jiffy 为单位, 1 jiffy=1/100 秒,另外不同硬件体系略有不同).
- stime %d
- 进程被调度进内核态的时间, 以 jiffy 为单位.
- cutime %d
- 进程及其子进程被调度进用户态的时间, 以 jiffy 为单位.
- cstime %d
- 进程及其子进程被调度进内核态的时间, 以 jiffy 为单位.
- counter %d
- 如果进程不是当前正在运行的进程, 就是进程在下个时间片当前可以拥有的最大时间, 以 jiffy 为单位. 如果进程是当前正在运行的进程, 就是当前时间片中所剩下 jiffy 数目.
- priority %d
- 标准优先数只再加上 15, 在内核里该值总是正的.
- timeout %u
- 当前至进程的下一次间歇时间, 以 jiffy 为单位.
- itrealvalue %u
- 由于计时间隔导致的下一个 SIGALRM 发送进程的时延,以 jiffy 为单位.
- starttime %d
- 进程自系统启动以来的开始时间, 以 jiffy 为单位.
- vsize %u
- 虚拟内存大小.
- rss %u
- Resident Set Size(驻留大小): 进程所占用的真实内存大小, 以页为单位, 为便于管理而减去了 3. rss 只包括正文, 数据以及堆栈的空间, 但不包括尚未要求装入内存的或已被交换出去的.
- rlim %u
- 当前进程的 rss 限制, 以字节为单位, 通常为 2,147,483,647.
- startcode %u
- 正文部分地址下限.
- endcode %u
- 正文部分地址上限.
- startstack %u
- 堆栈开始地址.
- kstkesp %u
- esp(32 位堆栈指针) 的当前值, 与在进程的内核堆栈页得到的一致.
- kstkeip %u
- EIP(32 位指令指针)的当前值.
- signal %d
- 待处理信号的 bitmap(通常为 0).
- blocked %d
- 被阻塞信号的 bitmap(对 shell 通常是 0, 2).
- sigignore %d
- 被忽略信号的 bitmap.
- sigcatch %d
- 被俘获信号的 bitmap.
- wchan %u
- 进程在其中等待的通道, 实际是一个系统调用的地址. 如果你需要文本格式的, 也可以在名字列表中找到. (如果有最新版本的 /etc/psdatabase, 你可以在 ps -l 的结果中的 WCHAN 域看到)
- cpuinfo
- 保存了CPU 以及体系架构依赖条目的列表. 对于不同的系统架构有不同的列表, 共有的两项是 cpu 和 BogoMIPS, cpu 可能是当前在用的 CPU, 而 BogoMIPS 则是内核初始化时计算出的一个系统常数.
- devices
- 主设备号及设备组的列表, 文本格式. MAKEDEV 脚本使用该文件来维持内核的一致性.
- dma
- 一个列表, 指出正在使用的ISA DMA (直接内存访问)通道.
- filesystems
- 以文本格式列出了被编译进内核的文件系统. 当没有给 mount(1) 指明哪个文件系统的时候, mount(1) 就依靠该文件遍历不同的文件系统.
- interrupts
- 该文件以 ASCII 格式记录了(至少是在 i386 体系上的)每次 IRQ 的中断数目.
- ioports
- 该文件列出了当前在用的已注册 I/O 端口范围.
- kcore
- 该伪文件以 core 文件格式给出了系统的物理内存映象, 再利用未卸载的内核 (/usr/src/linux/tools/zSystem), 我们就可以用 GDB 查探当前内核的任意数据结构.
该文件的总长度是物理内存 (RAM) 的大小再加上 4KB.
- kmsg
- 可以用该文件取代系统调用 syslog(2) 来记录内核信息. 但是读该文件需要超级用户权限, 并且一次只能有一个进程可以读该文件, 因而如果一个使用了 syslog(2) 系统调用功能来记录内核信息的系统日志进程正在运行的话, 别的进程就不能再去读该伪文件了.
该文件的内容可以用 dmesg(8) 来察看.
- ksyms
- 该文件保存了内核输出的符号定义, modules(X) 使用该文件动态地连接和捆绑可装载的模块.
- loadavg
- 平均负载数给出了在过去的 1, 5, 15 分钟里在运行队列里的任务数, 与 uptime(1) 等命令的结果相同.
- locks
- 这个文件显示当前文件锁.
- malloc
- 只有在编译时定义了 CONFIGDEBUGMALLOC 才会有该文件.
- meminfo
- free(1) 利用该文件来给出系统总的空闲内存和已用内存 (包括物理内存和交换内存), 以及内核所使用的共享内存和缓冲区.
该文件与 free(1) 格式相同, 但是以字节为单位而不是 KB.
- modules
- 列出了系统已载入的模块, 文本格式.
- net
- 该子目录包括多个 ASCII 格式的网络伪文件, 描述了网络层的部分情况. 可以用 cat 来察看这些文件, 但标准的 netstat(8) 命令组更清晰地给出了这些文件的信息.
- arp
- 该文件以 ASCII 格式保存了内核 ARP 表, 用于地址解析, 包括静态和动态 arp 数据. 文件格式如下:
IP address HW type Flags HW address 10.11.100.129 0x1 0x6 00:20:8A:00:0C:5A 10.11.100.5 0x1 0x2 00:C0:EA:00:00:4E 44.131.10.6 0x3 0x2 GW4PTS
其中 ‘IP address‘ 是机器的 IPv4 地址; ‘HW type‘ 是地址的硬件类型, 遵循 RFC 826; flags 是 ARP 结构的内部标志, 在 /usr/include/linux/if_arp.h 中定义; ‘HW address‘ 是该 IP 地址的物理层映射(如果知道的话).
- dev
- 该伪文件包含网络设备状态信息, 给出了发送和收到的包的数目, 错误和冲突的数目, 以及别的一些基本统计数据. ifconfig(8) 利用了该文件来报告网络设备状态. 文件格式如下:
Inter-| Receive | Transmit face |packets errs drop fifo frame|packets errs drop fifo colls carrier lo: 0 0 0 0 0 2353 0 0 0 0 0 eth0: 644324 1 0 0 1 563770 0 0 0 581 0
- ipx
- 无信息.
- ipx_route
- 无信息.
- rarp
- 该文件具有和 arp 同样的格式, 包含当前的逆向地址映射数据. rarp(8) 利用这些数据来作逆向地址查询服务. 只有将 RARP 配置进内核, 该文件才存在.
- raw
- 该文件保存了 RAW 套接字表, 大部分信息除用于调试以外没有什么用. 包括本地地址和协议号对; "St" 是套接字的内部状态; tx_queue 和 rx_queue 是内核存储器使用意义上的输入输出数据队列; RAW 没有使用"tr", "tm->when" 和 "rexmits"; uid 是套接字创建者的有效 uid.
- route
- 没有信息, 但是看上去类似于 route(8)
- snmp
- 该文件以 ASCII 格式保存了 IP, ICMP, TCP 以及 UDP 管理所需的数据信息, 基于 snmp 协议. TCP mib (TCP 管理数据库)尚未完善, 可能在 1.2.0 内核能够完成.
- tcp
- 该文件保存了 TCP 套接字表, 大部分信息除用于调试以外没有什么用. "sl" 指出了套接字的内核散列槽号; "local address" 包括本地地址和端口号; "remote address" 包括远地地址和端口号(如果有连接的话); ‘St‘ 是套接字的内部状态; ‘tx_queue‘ 和 ‘rx_queue‘ 是内核存储器使用意义上的输入输出数据队列; "tr", "tm->when" 和 "rexmits" 保存了内核套接字声明的内部信息, 只用于调试; uid 是套接字创建者的有效 uid.
- udp
- 该文件保存了 UDP 套接字表, 大部分信息除用于调试以外没有什么用. "sl" 指出了套接字的内核散列槽号; "local address" 包括本地地址和端口号; "remote address" 包括远地地址和端口号(如果有连接的话); "St" 是套接字的内部状态; "tx_queue" 和 "rx_queue" 是内核存储器使用意义上的输入输出数据队列; UDP 没有使用 "tr","tm->when" 和 "rexmits"; uid 是套接字创建者的有效 uid. 格式如下:
sl local_address rem_address st tx_queue rx_queue tr rexmits tm->when uid 1: 01642C89:0201 0C642C89:03FF 01 00000000:00000001 01:000071BA 00000000 0 1: 00000000:0801 00000000:0000 0A 00000000:00000000 00:00000000 6F000100 0 1: 00000000:0201 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0
- unix
- 列出了当前系统的UNIX域套接字以及它们的状态, 格式如下:
Num RefCount Protocol Flags Type St Path 0: 00000002 00000000 00000000 0001 03 1: 00000001 00000000 00010000 0001 01 /dev/printer
当前总是 0; ‘Flags‘ 是内核标志, 指出了套接字的状态; ‘Type‘ 当前总是 1(在内核中尚未支持 unix 域数据报套接字); ‘St‘ 是套接字内部状态; ‘Path‘ 套接字绑捆的路径(如果有的话).
- pci
- 该文件列出了内核初始化时发现的所有 PCI 设备及其配置.
- scsi
- 该目录包括 scsi 中间层伪文件及各种 SCSI 底层驱动器子目录, 对系统中每个 SCSI host, 子目录中都存在一个文件与之对应, 展示了部分 SCSI IO 子系统的状态. 这些文件是 ASCII 格式的, 可用cat阅读.
你也可以通过写其中某些文件来重新配置该子系统, 开关一些功能.
- scsi
- 该文件列出了内核掌握的所有 SCSI 设备, 其内容就和系统启动时所看到的类似. 目前 scsi 只支持 singledevice命令, 该命令允许 root 添加一个热插拔(hotplugged)设备到一个已知设备列表中.
命令 echo ‘scsi singledevice 1 0 5 0‘ > /proc/scsi/scsi 令 host scsi1 扫描 SCSI 通道 0, 看在 ID 5 LUN 0 是否存在设备, 如果在该地址存在设备, 或者该地址无效, 则返回一个错误.
- drivername
- 目前 drivername 可包含: NCR53c7xx, aha152x, aha1542, aha1740, aic7xxx, buslogic, eata_dma, eata_pio, fdomain, in2000, pas16, qlogic, scsi_debug, seagate, t128, u15-24f, ultrastore 或者 wd7000. 这些目录展示那些至少注册了一个 SCSI HBA 的驱动. 而对每个已注册的 host, 每个目录中都包含一个文件与之对应, 而这些对应的 host 文件就以初始化时分配给 host 的数字来命名.
这些文件给出了驱动程序以及设备的配置, 统计数据等.
可以通过写这些文件实现不同的 host 上做不同的工作. 例如, root 可以用 latency 和 nolatency 命令打开或者关闭 eata_dma 驱动器上测量延时的代码, 也可以用 lockup 和 unlock 命令控制 scsi_debug 驱动器所模拟的总线锁操作.
- self
- 当某进程访问 /proc 目录时, 该目录就指向 /proc 下以该进程 ID 命名的目录.
- stat
- 内核及系统的统计数据.
- cpu 3357 0 4313 1362393
- 系统分别消耗在用户模式, 低优先权的用户模式(nice), 系统模式, 以及空闲任务的时间, 以 jiffy 为单位. 最后一个数值应该是 uptime 伪文件第二个数值的 100 倍.
- disk 0 0 0 0
- 目前并没有实现这四个磁盘记录, 我甚至认为就不应该实现它,这是由于在别的机器上内核统计通常依赖转换率及每秒 I/O 数, 而这令每个驱动器只能有一个域.
- page 5741 1808
- 系统(从磁盘)交换进的页数和交换出去的页数.
- swap 1 0
- 取入的交换页及被取出的交换页的页数.
- intr 1462898
- 系统自启动以来所收到的中断数.
- ctxt 115315
- 系统所作的进程环境切换次数.
- btime 769041601
- 系统自 1970 年 1 月 1 号以来总的运行时间, 以秒为单位.
- sys
- 该目录在 1.3.57 的内核里开始出现, 包含一些对应于内核变量的文件和子目录. 你可以读这些变量, 有的也可以通过proc修改, 或者用系统调用 sysctl(2) 修改. 目前该目录下有如下三个子目录: kernel;, ;net;, ;vm 每个各自包括一些文件和子目录.
- kernel
- 该目录包括如下文件: domainname;, ;file-max;, ;file-nr;, ;hostname;, ; inode-max;, ;inode-nr;, ;osrelease;, ;ostype;, ; panic;, ;real-root-dev;, ;securelevel;, ;version, 由文件名就可以清楚地得知各文件功能.
只读文件 file-nr 给出当前打开的文件数.
文件 file-max 给出系统所容许的最大可打开文件数. 如果 1024 不够大的话, 可以
echo 4096 > /proc/sys/kernel/file-max
类似地, 文件 inode-nr 以及文件 inode-max 指出了当前 inode 数和最大 inode 数.
文件 ostype;, ;osrelease;, ;version 实际上是 /proc/version 的子字串.
文件 panic 可以对内核变量 panic_timeout 进行读/写访问.如果该值为零, 内核在 panic 时进入(死)循环; 如果非零, 该值指出内核将自动重起的时间, 以秒为单位.
文件 securelevel 目前似乎没什么意义 - root 无所不能.
- uptime
- 该文件包含两个数: 系统正常运行时间和总的空闲时间, 都以秒为单位.
- version
- 指明了当前正在运行的内核版本, 例如:
Linux version 1.0.9 ([email protected]) #1 Sat May 14 01:51:54 EDT 1994
以上是关于proc - 进程信息伪文件系统的主要内容,如果未能解决你的问题,请参考以下文章