Linux 中最重要的目录之 /proc

一、概述

Linux 系统中,一切皆为文件的理念提供了最高级的抽象,开发者只需要使用一套 API 就可以操作 Linux 系统中的绝大部分资源。

而在整个 Linux 目录树中, 有一个最重要的 (虚拟) 目录: /proc,在系统启动时创建,在系统关闭时销毁。

内核态通过简洁的文件内容 API 形式,将系统的大部分状态在用户态充分暴露出来,这样用户/程序直接读取 /proc 目录下面的相关文件,就可以获取到对应的系统/进程等状态和数据,真可谓大道至简。

总之,想要知道当前系统中运行了哪些进程、每个进程都打开了哪些文件、进程的 CPU、内存等使用情况如何、每个进程启动了几个线程、当前有哪些 TCP/UDP 连接、每个网卡收发的字节数等等,都可以在 /proc 目录中找到答案。

BTW, 直接读取 /proc 目录下面的文件内容,也是很多 Linux 常用命令和开源系统监控组件的实现原理。

本文主要从开发者使用 Linux 系统的角度,着重分析一下 /proc 目录下可以获取到的四类信息:

系统硬件/设备网络进程

二、系统相关

1. 内核版本/编译器/编译时间
复制
$ cat /proc/version Linux version 6.6.87+ (builder@f33bfd62b873) (Chromium OS 17.0_pre498229-r33 clang version 17.0.0 (/var/cache/chromeos-cache/distfiles/egit-src/external/github.com/llvm/llvm-project 14f0776550b5a49e1c42f49a00213f7f3fa047bf), LLD 17.0.0) #1 SMP PREEMPT_DYNAMIC Sat May 3 09:33:57 UTC 20251.2.3.

可以看到,输出的信息远比 uname 命令获取到内容要详细。

复制
$ uname -a Linux cs-100667547897-default 6.6.87+ #1 SMP PREEMPT_DYNAMIC Sat May 3 09:33:57 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux1.2.3.
2. 系统负载

输出系统最近 1/5/15 分钟的平均负载。

复制
$ cat /proc/loadavg 0.03 0.01 0.00 1/300 12721.2.3.

对比 uptime 命令的输出:

复制
$ uptime 14:12:36 up 7:44, 0 user, load average: 0.03, 0.01, 0.001.2.3.
3. 硬中断

输出系统中的硬件中断情况,按照 CPU 进行分组。

复制
$ cat /proc/interrupts # output CPU0 CPU1 0: 269 0 IO-APIC 0-edge timer 1: 0 9 IO-APIC 1-edge i8042 4: 0 2067 IO-APIC 4-edge ttyS0 6: 70 0 IO-APIC 6-edge 8: 0 0 IO-APIC 8-edge rtc0 9: 0 0 IO-APIC 9-fasteoi acpi 10: 0 16876 IO-APIC 10-fasteoi virtio2 ...1.2.3.4.5.6.7.8.9.10.11.12.13.14.
4. 软中断

输出系统中的硬件中断情况,按照 CPU 进行分组。

复制
$ cat /proc/softirqs # output CPU0 CPU1 HI: 0 0 TIMER: 98735 84868 NET_TX: 2 4 NET_RX: 18737 28301 BLOCK: 0 29051 IRQ_POLL: 0 0 TASKLET: 44 30 SCHED: 200114 198635 HRTIMER: 0 0 RCU: 57886 617361.2.3.4.5.6.7.8.9.10.11.12.13.14.15.

每个 CPU 都对应一个软中断内核线程运行状况,所以使用下面的命令,也可以获取到 CPU 软中断运行情况。

复制
$ ps aux | grep softirq1.
5. 内核参数

通过读写文件来动态调整内核参数,例如在TCP 100 万长连接的参数调优[2] 一文中,就涉及到很多 /proc/sys 目录下面相关文件的参数修改,限于篇幅,这里不再赘述了。

三、硬件相关

1. CPU

输出机器上所有 (逻辑) CPU 型号、核心数、频率等详细信息。

复制
$ cat /proc/cpuinfo processor : 0 vendor_id : GenuineIntel cpu family : 6 ... processor : 1 vendor_id : GenuineIntel cpu family : 6 ...1.2.3.4.5.6.7.8.9.10.11.12.13.

可以在此基础上计算出 (逻辑) CPU 的数量。

复制
$ cat /proc/cpuinfo | grep processor | wc -l1.

常用的 Linux 命令中的 lscpu,输出的源数据就来自 /proc/meminfo 文件。

2. 内存

输出机器上物理内存、交换分区、缓存等信息。

复制
$ cat /proc/meminfo MemTotal: 8138112 kB MemFree: 6372192 kB MemAvailable: 7426484 kB Buffers: 74336 kB Cached: 1177368 kB SwapCached: 0 kB ...1.2.3.4.5.6.7.8.9.10.

常用的 Linux 命令中的 free 和 top,输出的源数据就来自 /proc/meminfo 文件。

复制
$ free total used free shared buff/cache available Mem: 8138112 711636 6372192 1108 1301156 7426476 Swap: 0 0 01.2.3.4.5.

四、网络相关

1. 网卡数据统计

输出网卡接口的统计信息,例如发送数据量、接收数据量、错误数量。

复制
$ cat /proc/net/dev Inter-| Receive | Transmit face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed lo: 31272563 12256 0 0 0 0 0 0 31272563 12256 0 0 0 0 0 0 eth0: 6263742 24376 0 0 0 0 0 0 18041254 18792 0 0 0 0 0 0 docker0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 01.2.3.4.5.6.7.

常用的 ifconfig 命令,数据源就是 /proc/net/dev 文件。

复制
$ ifconfig docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1460 ... RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1460 ... RX packets 24328 bytes 6256091 (6.2 MB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 18758 bytes 18034626 (18.0 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 ... RX packets 12216 bytes 31268081 (31.2 MB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 12216 bytes 31268081 (31.2 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 01.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.
2. 网络连接状态和对列

输出 TCP/UDP 网络连接,及其对应的端口号和状态等信息。

复制
$ cat /proc/net/tcp $ cat /proc/net/udp1.2.3.

常用的 Linux 网络命令中, netstat 和 ss 命令就是对 /proc/net/tcp、/proc/net/udp、/proc/net/raw 等文件内容进行了二次加工,具体的过程这里就不展开了 🙂 。

下面是使用 netstat 和 ss 命令的输出结果:

复制
$ netstat -ant1.

复制
$ ss -ant1.

3. ARP 表

ARP 表存储着当前局域网中各主机的 IP 地址到 MAC 地址的映射关系。

复制
$ cat /proc/net/arp IP address HW type Flags HW address Mask Device 10.88.0.1 0x1 0x2 12:a5:12:b7:15:70 * eth01.2.3.4.

下面是对等的 arp 命令。

复制
$ arp -an ? (10.88.0.1) at 12:a5:12:b7:15:70 [ether] on eth01.2.3.

五、进程相关

每个进程都有一个进程 ID (数字) pid,所以和进程相关的信息都在目录 /proc/{pid} 下面。

例如下面展示了 root 用户打开的相关进程:

复制
... dr-xr-xr-x 9 root root 0 May 19 23:19 207/ dr-xr-xr-x 9 root root 0 May 19 23:19 25/ dr-xr-xr-x 9 root root 0 May 19 23:19 26/ dr-xr-xr-x 9 root root 0 May 19 23:19 264/ dr-xr-xr-x 9 root root 0 May 19 23:20 270/ dr-xr-xr-x 9 root root 0 May 19 23:19 271/ dr-xr-xr-x 9 root root 0 May 19 23:20 275/ dr-xr-xr-x 9 root root 0 May 19 23:19 285/ dr-xr-xr-x 9 root root 0 May 19 23:19 296/ dr-xr-xr-x 9 root root 0 May 19 23:20 467/ ...1.2.3.4.5.6.7.8.9.10.11.12.13.14.

下文的示例中,统一以笔者机器上运行的 dockerd 进程为例,进行代码和命令输出结果演示。

复制
root 207 1 0 23:19 ? 00:00:00 /usr/bin/dockerd -p /var/run/docker.pid --mtu=14601.

演示 docker 进程 pid = 207

1. 启动参数

输出进程的启动命令及其参数。

复制
$ sudo cat /proc/207/cmdline /usr/bin/dockerd-p/var/run/docker.pid--mtu=14601.2.3.
2. 进程状态

输出进程的 pid、ppid、内存使用等信息。

复制
$ sudo cat /proc/207/status # output Name: dockerd Umask: 0022 State: S (sleeping) Tgid: 207 Ngid: 0 Pid: 207 PPid: 1 ... Threads: 10 ... Cpus_allowed: 3 Cpus_allowed_list: 0-1 Mems_allowed: 00000000,00000001 Mems_allowed_list: 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.
3. 函数调用栈

输出进程当前正在执行的的函数调用栈。

复制
$ sudo cat /proc/207/stack # output [<0>] futex_wait_queue+0xdd/0x130 [<0>] futex_wait+0x179/0x300 [<0>] do_futex+0x18f/0x1e0 [<0>] __se_sys_futex+0x152/0x1d0 [<0>] do_syscall_64+0x46/0xb0 [<0>] entry_SYSCALL_64_after_hwframe+0x78/0xe21.2.3.4.5.6.7.8.9.10.
4. 线程状态

输出进程

复制
$ sudo ls -l /proc/207/task/ # output total 0 dr-xr-xr-x 7 root root 0 May 20 13:43 206 dr-xr-xr-x 7 root root 0 May 20 13:44 212 dr-xr-xr-x 7 root root 0 May 20 13:44 213 dr-xr-xr-x 7 root root 0 May 20 13:44 214 dr-xr-xr-x 7 root root 0 May 20 13:44 215 dr-xr-xr-x 7 root root 0 May 20 13:44 221 dr-xr-xr-x 7 root root 0 May 20 13:44 229 dr-xr-xr-x 7 root root 0 May 20 13:44 249 dr-xr-xr-x 7 root root 0 May 20 13:44 263 dr-xr-xr-x 7 root root 0 May 20 13:44 2751.2.3.4.5.6.7.8.9.10.11.12.13.14.15.

下面是使用 pstree 命令输出的线程结果。

复制
$ pstree -p 2071.

5. 打开文件

输出 dockerd 进程打开的所有文件句柄 (fd)。

复制
$ sudo ls -l /proc/207/fd/1.

6. 内存映射

输出进程内存映射区域(例如堆、共享库),smaps 细化到每个区域的 RSS 和脏页统计,用于内存泄漏分析 (具体的分析方法,感兴趣的读者可以自行搜索)。

复制
$ sudo cat /proc/212/maps1.

复制
$ sudo cat /proc/212/smaps1.

会逐行输入类似如下的内存映射信息:

Linux 命令中的 pmap 的数据源就是 maps 和 smaps 文件。

复制
$ sudo pmap -x 2071.

7. OOM

Linux 内核 OOM killer 会在内存不足时,选择性地杀掉用户进程。

它的运行规则简单来说就是,OOM killer 会为每个用户进程设置一个权重值,这个权重值越高,被 kill 的概率越高,反之概率越低。

每个进程的权重值存放在 /proc/{pid}/oom_adj 中,大多数进程的默认权重值都是 0。

复制
$ sudo cat /proc/207/oom_adj1.
8. 网络连接

进程网络相关的文件都在 /proc/{pid}/net 目录下面,可以根据不同的协议类型查看对应的文件,输出结果和 /proc/net/ 下面的文件基本类似,限于篇幅,这里就不再赘述了。

六、小结

THE END