探索 Linux 系统中的内存使用情况
在 Linux 系统中,有多种方法可以帮助你了解内存的使用状况。本文将介绍几种最常用的命令行工具,包括 free
、vmstat
和 top
,此外,我们还会直接分析 /proc/meminfo
文件来获取内存信息。
Linux 如何管理内存(RAM)?
RAM 是系统中所有进程(如应用程序和后台服务)都需要的宝贵资源。它的容量是有限的。内核负责管理内存分配,它会根据进程的需要来分配内存,就像一个鸟妈妈需要给很多张开小嘴的幼鸟喂食一样。
当 RAM 没有被使用时,其实是一种资源的浪费。Linux 会利用空闲的 RAM 来存储文件缓冲区等数据,从而优化系统性能。有时你可能会觉得系统的 RAM 被某些失控的进程或内存泄漏占用了,但实际上这种情况很少见。
通常,内核只是在后台默默地工作。如果内核分配给自身设备的 RAM 有其他用途,它会立即释放内存,所以不会造成任何损害。
此外,如果内核认为使用交换空间(swap)更有效,它也会开始利用。关于 Linux 中的 swappiness 值以及内核何时开始使用交换空间存在一些误解。swappiness 值并不是触发交换启用的 RAM 使用阈值。
接下来,让我们来看看在终端窗口中可以使用的不同技术,以监控 Linux 计算机上的 RAM 使用情况。
free
命令
free
命令可以显示计算机的总内存、已用内存、可用内存、共享内存、缓冲区/缓存以及可用的 RAM 的表格。它还会显示配置的交换空间总量,以及已使用和可用的空间量。
在我们的示例中,我们将使用 -m
选项(以兆字节为单位)。你也可以使用 -b
(字节)、-k
(千字节)或 -g
(千兆字节)选项。
输入以下命令:
free -m
输出结果如下:
total used free shared buff/cache available Mem: 1987 901 95 80 990 811 Swap: 1521 651 869
Mem
列包含以下信息:
- total:计算机的物理 RAM 总量。
- used:已用内存量,计算方式为 total 减去 free、buffers 和 cache 的总和。
- free:未使用的内存量。
- shared:tmpfs 文件系统使用的内存量。
- buff/cache:用于缓冲区和缓存的内存量。内核可以根据需要快速释放这部分内存。
- available:估计可用于应用程序和其他系统软件的内存量。
Swap
列包含以下信息:
- Total:交换分区或文件的大小。
- Used:正在使用的交换空间量。
- Free:剩余(未使用)的交换空间量。
你还可以使用以下命令来查看已使用的交换空间百分比:
free -m | grep Swap | awk '{print ($3/$2)*100}'
vmstat
命令
了解 Linux 机器中 RAM 的使用情况,也需要了解交换空间的状态。RAM 和交换空间是紧密协作的。
可以使用 vmstat
命令更深入地了解交换空间(或虚拟内存)的使用情况。它会提供基于上次重启以来的平均值的各种交换相关统计报告。
输入以下命令:
vmstat
输出结果如下:
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 3 0 671488 576084 51088 823876 1 7 53 62 99 14 4 1 95 0 0
该报告有很多数据点,下面我们来逐一分析:
进程 (procs):
- r:“可运行”进程的数量。这些进程要么正在运行,要么正在等待 CPU 时间。
- b:处于不可中断睡眠状态的进程数。这些进程不是在休眠,而是在执行阻塞系统调用。在完成当前操作之前,它们无法被打断。通常,这可能是设备驱动程序正在等待某些资源释放。当进程恢复其通常的活动时,会处理该进程的任何排队中断。
内存 (memory):
- swpd:使用的虚拟内存量,即已换出到交换空间的内存量。
- free:空闲(未使用)的内存量。
- buff:用作缓冲区的内存量。
- cache:用作缓存的内存量。
交换空间 (swap):
- si:从交换空间换入的虚拟内存量。
- so:换出到交换空间的虚拟内存量。
I/O (io):
- bi:从交换空间换回 RAM 的数据块数。
- bo:从 RAM 换出到交换空间的数据块数。
系统 (system):
- in:每秒中断次数,包括时钟中断。
- cs:每秒上下文切换次数。上下文切换是指内核在系统和用户模式之间切换。
CPU:这些值都是总 CPU 时间的百分比:
- us:运行用户(非内核)代码所花费的时间。
- sy:运行内核代码所花费的时间。
- id:CPU 空闲时间。
- wa:等待 I/O 所花费的时间。
- st:虚拟机必须等待虚拟机管理程序完成服务其他虚拟机才能返回并处理此虚拟机的时间。
top
命令
top
命令可以实时显示系统资源使用情况。它会定期更新屏幕上的信息。
要使用它,请输入以下命令:
top
在 top
命令运行时,按下 e
键可以将内存显示单位切换为兆字节 (MB),这样更容易查看内存使用情况。屏幕顶部有五行信息,下方窗格中是各个进程的详细数据。
以下是每一行信息的含义:
- 第一行:时间、计算机运行时间、已登录用户数以及过去 1 分钟、5 分钟和 15 分钟的平均负载。
- 第二行:任务数量及其状态:运行、停止、睡眠或僵尸。
- 第三行:CPU 信息(请参考下面的字段说明)。
- 第四行:物理内存总量,以及空闲、已用、缓冲和缓存的内存量。
- 第五行:交换内存总量,以及空闲、已用和可用(考虑到预计可从缓存恢复的内存)的内存量。
第三行的 CPU 字段说明如下:
- us:CPU 为用户空间中的用户执行进程所花费的时间。
- sy:CPU 运行系统“内核空间”进程所花费的时间。
- ni:CPU 使用手动设置的 nice 值执行进程所花费的时间。
- id:CPU 空闲时间。
- wa:CPU 等待 I/O 完成所花费的时间。
- hi:CPU 用于服务硬件中断的时间。
- si:CPU 用于服务软件中断的时间。
- st(窃取时间):由于运行虚拟机而丢失 CPU 的时间。
你可能需要使用左右箭头键来查看所有列。以下是每一列的含义:
- PID:进程 ID。
- USER:进程所有者的用户名。
- PR:进程优先级。
- NI:进程的 nice 值。
- VIRT:进程使用的虚拟内存。
- RES:进程使用的常驻内存。
- SHR:进程使用的共享内存。
- S:进程的状态(请参阅下面的列表)。
- %CPU:自上次更新以来进程使用的 CPU 时间百分比。
- %MEM:进程使用的物理内存百分比。
- TIME+:任务在 100 分之一秒内使用的总 CPU 时间。
- COMMAND:命令名称或行(名称 + 选项)。 (此列可能位于右侧的屏幕外。)
S 列中可能显示的状态包括:
- D:不可中断的睡眠。
- R:运行中。
- S:睡眠中。
- T:跟踪(停止)。
- Z:僵尸。
按下 q
键可以退出 top
命令。
读取 /proc/meminfo
Linux 中很多(可能是大多数)报告内存统计的工具都是从 /proc/meminfo
这个虚拟文件系统中获取信息的。我们可以使用 cat
或 less
命令来查看这个文件。
输入以下命令:
less /proc/meminfo
根据运行的内核和 CPU 架构,你可能会看到不同的字段。 以下是我们在虚拟机上得到的结果:
MemTotal: 2035260 kB MemFree: 919064 kB MemAvailable: 1300932 kB Buffers: 33528 kB Cached: 457604 kB SwapCached: 29732 kB Active: 313360 kB Inactive: 603276 kB Active(anon): 74648 kB Inactive(anon): 355004 kB Active(file): 238712 kB Inactive(file): 248272 kB Unevictable: 16 kB Mlocked: 16 kB SwapTotal: 1557568 kB SwapFree: 873024 kB Dirty: 80 kB Writeback: 0 kB AnonPages: 414100 kB Mapped: 97436 kB Shmem: 4148 kB KReclaimable: 52932 kB Slab: 94216 kB SReclaimable: 52932 kB SUnreclaim: 41284 kB KernelStack: 9280 kB PageTables: 45264 kB NFS_Unstable: 0 kB Bounce: 0 kB WritebackTmp: 0 kB CommitLimit: 2575196 kB Committed_AS: 5072192 kB VmallocTotal: 34359738367 kB VmallocUsed: 35712 kB VmallocChunk: 0 kB Percpu: 720 kB HardwareCorrupted: 0 kB AnonHugePages: 0 kB ShmemHugePages: 0 kB ShmemPmdMapped: 0 kB CmaTotal: 0 kB CmaFree: 0 kB HugePages_Total: 0 HugePages_Free: 0 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB Hugetlb: 0 kB DirectMap4k: 180160 kB DirectMap2M: 1916928 kB
除非另有说明,否则所有尺寸都以千字节为单位。下面是它们的所有含义,以及你可能看到的一些其他含义,具体取决于你的计算机配置和硬件:
- MemTotal:可用 RAM 总量(除去一些保留位和内核二进制代码)。
- MemFree:
LowFree
+HighFree
之和。当前可用的 RAM 量。 - MemAvailable:估计可用于启动新应用程序的内存,而无需使用交换空间。
- Buffers:原始磁盘块的临时存储。这减少了硬盘的 I/O 操作。它也加快了对相同数据的后续请求的访问,因为这些数据已在内存中。
- Cached:从硬盘驱动器上的文件读取的缓存页面(不包括
SwapCached
)。 - SwapCached:换出和换回的内存,副本保留在交换空间中。
- Active:最近使用的内存。除非绝对必要,否则不会回收。
- Inactive:已使用但不是最近使用的内存。可能是回收的候选。
- Active(anon):分配给 tmpfs 虚拟文件系统上的文件的内存。匿名文件不驻留在硬盘驱动器上。
- Inactive(anon):匿名的、tmpfs 和 shmem 的内存量,这些内存可以被释放(内存回收)。
- Active(file):正在使用的文件缓存内存量,或者自上一次内存回收周期以来已使用的内存量。
- Inactive(file):从硬盘驱动器读取的文件缓存内存量,可以被回收。
- Unevictable:应该是可驱逐的内存量,但由于它被用户空间进程锁定在内存中而无法驱逐。
- Mlocked:由于用户空间进程将其锁定,因此无法驱逐的内存总量。
- HighTotal:
HighMem
的总量,用于用户空间程序和页面缓存。内核可以访问这个内存区域,但访问速度比LowMem
慢。 - HighFree:空闲的
HighMem
数量。 - LowTotal:
LowMem
的数量,可用于与HighMem
相同的用途,但内核也可以将其用于自己的目的。 - LowFree:空闲的
LowMem
数量。 - MmapCopy:映射到文件数据的内存量。
- SwapTotal:可用的交换空间总量。
- SwapFree:当前未使用的交换空间量。
- Dirty:等待写回磁盘的内存量。
- Writeback:正在主动写回磁盘的内存。
- AnonPages:映射到用户空间页表的非文件支持页面。
- Mapped:映射到内存的文件(例如库)。
- Shmem:在 tmpfs 虚拟文件系统中消耗的内存量。
- KReclaimable:如果内存需求足够严重,内核会尝试回收的内核内存分配。
- Slab:内核数据结构缓存。
- SReclaimable:可能被回收的 Slab 内存量,例如缓存。
- SUnreclaim:无法回收的 Slab 内存量。
- KernelStack:分配给内核堆栈的内存量。
- PageTables:专用于最低级别页表的内存量。
- Quicklists:由于页表的分配和删除是一项非常频繁的操作,因此尽快完成分配和删除至关重要。因此,页表使用的页面被缓存在许多不同的列表中,这些列表称为“快速列表”。
- NFS_Unstable:网络文件系统 (NFS) 服务器已接收但尚未写入非易失性存储的页面。
- Bounce:用于块设备反弹缓冲区的内存。反弹缓冲区位于足够低的内存中,以便设备可以直接访问它。然后,数据被复制到
HighMem
中所需的用户页面。 - WritebackTmp:用于用户空间文件系统 (FUSE) 临时写回缓冲区的内存。
- CommitLimit:系统当前可分配的总内存量。
- Committed_AS:估计满足所有当前需求的内存量。如果程序请求一些 RAM,则会记录该请求,但仅在程序开始使用它时才会分配 RAM。并且只会根据需要分配,直到程序保留的最大量。可以“分配”的内存可能比实际交付的内存多。如果所有程序都试图一次兑现它们的 RAM 支票,那么内存赌场可能会破产(并且不得不向交换空间提供商寻求帮助)。
- VmallocTotal:
vmalloc
内存区的总大小。 - VmallocUsed:已使用的
vmalloc
区域数量。从 Linux 4.4 开始,不再计算此字段,而是进行硬编码。 - VmallocChunk:空闲
vmalloc
区域的最大连续块。 - HardwareCorrupted:标记为存在物理内存损坏的内存量。不会分配。
- LazyFree:
MADV_FREE
状态的内存量。当应用程序在一系列页面上设置MADV_FREE
标志时,它表明它不再需要它们,并且它们现在是回收的候选。实际回收可能会延迟到对内存有足够需求的时候。如果应用程序开始写入页面,则可以取消回收。 - AnonHugePages:映射到用户空间页表的非文件支持大页面。非文件支持页面不是来自硬盘驱动器文件。
- ShmemHugePages:共享内存(shmem)和分配有大页的虚拟文件系统(tmpfs)使用的内存量。
- ShmemPmdMapped:映射到大页面的用户空间的共享内存量。
- CmaTotal:CMA(连续内存分配器)页面的数量。这些由只能与内存的连续区域进行通信的设备使用。
- CmaFree:空闲的 CMA(连续内存分配器)页面的数量。
- HugePages_Total:大页面池的大小。
- HugePages_Free:池中未分配的大页面数。
- HugePages_Rsvd:保留的大页面数。已作出分配的承诺,但尚未发生分配。
- HugePages_Surp:池中超出定义系统值的大页面数。
- Hugepagesize:大页面的大小。
- DirectMap4k:映射到 4kB 页面的 RAM 字节数。
- DirectMap2M:映射到 2MB 页面的 RAM 字节数。
- DirectMap4M:映射到 4MB 页面的 RAM 字节数。
- DirectMap1G:映射到 2GB 页面的 RAM 字节数。
和 Linux 的其他方面一样,有很多方法可以快速概览系统信息,并且总是有至少一种方法可以更深入地了解细节。
你可能会定期使用 free
、top
和 vmstat
命令,而将 /proc/meminfo
文件留作需要深入研究特定问题时使用。