【Linux】top中的VIRT=RES+SHR的等式是否成立?
先说结论:VIRT
并不等于 RES
+ SHR
。它们的关系需要从每个字段的含义和它们分别代表的内存类型来理解
1. VIRT(虚拟内存大小)
-
VIRT 表示进程所占用的 虚拟内存 总量。它包含了进程请求的所有虚拟内存空间,包括:
- 进程的代码段(可执行文件)
- 堆和栈
- 映射的文件(例如通过
mmap()
映射的文件) - 动态链接的库(共享库)
- 虚拟内存区域(如未分配的内存空间)
-
VIRT 包括了进程所有的虚拟地址空间,不管这些地址是否已经映射到物理内存中。因此,VIRT 包含了大量可能尚未实际使用的虚拟内存。
2. RES(常驻内存大小)
-
RES 是进程实际 占用的物理内存(RAM)大小。它表示的是进程 当前已加载到物理内存中的部分,包括:
- 代码段、堆、栈等
- 共享的内存区域(例如,进程加载的共享库和通过
shmget()
创建的共享内存段)
-
RES 不包括尚未映射到物理内存的虚拟内存区域,比如映射的文件或懒加载的共享库。RES 是实际占用物理内存的大小。
3. SHR(共享内存大小)
-
SHR 表示进程所使用的 共享内存 的大小。共享内存是多个进程之间共享的内存区域,如:
- 共享库(例如
libc
) - 共享内存段(通过
shmget()
和shmat()
创建的内存区域)
- 共享库(例如
-
共享内存是多个进程共享的部分,因此它不计入单个进程的独占内存。例如,如果多个进程加载相同的共享库,它们会共享这部分内存,而不重复计算。
4. %MEM(内存使用百分比)
- %MEM 表示进程实际占用的物理内存(即 RES)占整个系统物理内存的百分比。
- 它的计算公式是:
%MEM = (RES / 总物理内存) * 100
关系总结:
-
VIRT 是进程的虚拟地址空间的总量,它通常大于 RES,因为它包含了进程请求的所有内存区域,而不仅仅是映射到物理内存的部分。VIRT 包括了进程的 堆、栈、共享库 等,还包括了那些尚未分配或映射的内存部分。
-
RES 是进程实际占用的物理内存,它比 VIRT 小。RES 包含了进程已经映射到物理内存的部分,比如代码段、栈、堆以及共享内存段。
-
SHR 表示进程使用的 共享内存 部分,通常包括共享库和共享内存段。SHR 是 RES 的一部分,因为共享内存实际上是映射到物理内存中的,所以它会占用 RES 中的部分内存。
为什么 VIRT 不等于 RES + SHR?
- VIRT 包含了进程的所有虚拟内存,包括那些尚未映射到物理内存的部分,而 RES 只包含已经映射到物理内存的部分。
- SHR 是 RES 的一部分,表示共享的内存。SHR 不会被重复计算,因为共享内存是多进程共享的,所以不会占用进程独占的物理内存。
- 由于 VIRT 还包括未加载的内存(如共享库的懒加载部分、映射的文件等),它通常比 RES + SHR 大,且不等于两者之和。
举个例子:
假设有一个进程,my_process
,其内存使用如下:
VIRT | RES | SHR |
---|---|---|
200 MB | 80 MB | 30 MB |
- VIRT 为 200 MB,表示进程总的虚拟内存空间,包括代码、堆、共享库、映射文件等。
- RES 为 80 MB,表示进程实际占用的物理内存。
- SHR 为 30 MB,表示进程与其他进程共享的内存区域。比如,
my_process
与其他进程共享libc
库。
在这个例子中:
- VIRT 不是 RES + SHR,因为 VIRT 还包含了 RES 外的虚拟内存区域(例如尚未映射到物理内存的部分)。
- RES 包括了进程实际占用的物理内存,而 SHR 表示它共享的内存部分,且共享内存的大小被计算到 RES 中。
所以结论:
- VIRT 是进程的虚拟内存总量,通常比 RES 和 SHR 的和要大。
- RES 是进程实际使用的物理内存,SHR 是进程与其他进程共享的内存。
- 因为 VIRT 包含了多种内存区域,且 RES 和 SHR 各自包含特定类型的内存,所以 VIRT 不等于 RES + SHR。