Linux top、VIRT、RES、SHR、SWAP(S)、DATA Memory Parameters Detailed
catalog
1. Linux TOP指令 2. VIRT -- Virtual Image (KB) 3. RES -- Resident size (KB) 4. SHR -- Shared Memory size (KB) 5. SWAP -- Swapped size (KB) 6. DATA -- Data+Stack size (KB) 7. 进程内存统计情况内核态表示 8. Glibc、Glibc运行时库内存池管理对进程内存使用统计情况的影响
1. Linux TOP指令
top 命令是最流行的性能监视工具之一,我们必需了解。它是一个优秀的交互式工具,用于监视性能。它提供系统整体性能,但报告进程信息才是 top 命令的长处。top 命令交互界面如下图所视
top 界面分为两个部份,光标上面部份显示关于系统整体性能,光标下面部份显示各进程信息。光标所在处是用来输入操作命令的
0x1: 第一行
1. top: 名称 2. 15:21:20: 系统当前时间 3. up: 1 day 4. 2:10: 系统开机到现在经过了多少时间 5. 1 user: 当前1个用户在线 6. load average: 0.00, 0.01, 0.05: 系统1分钟、5分钟、15分钟的CPU负载信息
0x2: 第二行
1. Tasks: 任务 2. 104 total: 当前有104个任务,即104个进程 3. 1 running: 1个进程正在运行 4. 103 sleeping: 103个进程睡眠 5. 0 stopped: 0个停止的进程 6. 0 zombie: 0个僵死的进程
0x3: 第三行
1. %Cpu(s): 显示CPU总体信息 2. 0.2 us: 进程占用CPU时间百分比为0.2% 3. 0.2 sy: 内核占用CPU时间百分比为0.2% 4. 0.0 ni: renice值为负的任务的用户态进程的CPU时间百分比,nice是优先级的意思 5. 99.5 id: 空闲CPU时间百分比 6. 0.0 wa: 等待I/O的CPU时间百分比 7. 0.0 hi: CPU硬中断时间百分比 8. 0.0 si: CPU软中断时间百分比 9. 0.2 st
0x4: 第四行
1. KiB Mem: 内存 2. 2048496 total: 物理内存总量 3. 226356 used: 使用的物理内存量 4. 1822140 free: 空闲的物理内存量 5. 34060 buffers: 用作内核缓存的物理内存量
0x5: 第五行
1. KiB Swap: 交换空间 2. 0 total: 交换区总量 3. 0 used: 使用的交换区量 4. 0 free: 空闲的交换区量 5. 117004 cached Mem: 缓冲交换区总量
0x6: 第六行
1. PID: 进程的ID 2. USER: 进程的所有者 3. PR: 进程的优先级别,越小优先级别越高 4. NI: NInice值 5. VIRT: 进程占用的虚拟内存 6. RES: 进程占用的物理内存 7. SHR: 进程使用的共享内存 8. S: 进程的状态 1) S表示休眠 2) R表示正在运行 3) Z表示僵死状态 4) N表示该进程优先值为负数 9. %CPU: 进程占用的CPU使用率 10. %MEM: 进程使用的物理内存和总内存的百分比 11. TIME+: 该进程启动后占用的总的CPU时间,即占用CPU使用时间的累加值 12. COMMAND: 进程启动命令名称
Relevant Link:
http://os.51cto.com/art/201108/285581.htm
2. VIRT -- Virtual Image (KB)
Thetotal amount of virtual memory used by the task. It includes all code, data andshared libraries plus pages that have been swapped out. (一个任务所使用的虚拟内存的总数。它包括所有的代码,数据和共享库,加上已换出的页面)
VIRT = SWAP +RES (公式1)
从本质上讲,虚拟内存并不能完全说明一个进程的内存占用情况,因为并不是所有虚拟内存对一一映射到物理内存页
Relevant Link:
http://javawind.net/p131
3. RES -- Resident size (KB)
The non-swappedphysical memory a task has used. (一个任务正在使用的没有交换的物理内存)我们一般称为驻留内存空间,也即一个进程实际占用的物理内存页
RES = CODE + DATA
4. SHR -- Shared Memory size (KB)
The amount ofshared memory used by a task. It simply reflects memory that could bepotentially shared with other processes. (一个任务使用共享内存的总数。它只是反映可能与其它进程共享的内存)也就是这个进程使用共享内存的大小
5. SWAP -- Swapped size (KB)
Theswapped out portion of a task’s total virtual memory image. (换出一个任务的总虚拟镜像的一部分)只是说明了交换的内存来自虚拟内存,但没说明把什么样的内存交换出去
6. DATA -- Data+Stack size (KB)
Theamount of physical memory devoted to other than executable code, also known asthe ’data resident set’ size or DRS. (除可执行代码以外的物理内存总量,也被称为数据驻留集或DRS
7. 进程内存统计情况内核态表示
top里面描述进程内存使用量的数据来源于/proc/$pid/statm这个文件,我们通过观察kernel的代码来理解它们的本质含义,Linux通过一个叫做 task_statm 的函数来返回进程的内存使用状况
/source/fs/proc/task_mmu.c
int task_statm(struct mm_struct *mm, int *shared, int *text, int *data, int *resident) { //shared代表了page cache里面实际使用了的物理内存的页数 *shared = get_mm_counter(mm, file_rss); //text代表了代码所占用的页数 *text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK)) >> PAGE_SHIFT; //data是总虚拟内存页数减去共享的虚拟内存页数 *data = mm->total_vm - mm->shared_vm; //resident是所有在使用的物理内存的页数 *resident = *shared + get_mm_counter(mm, anon_rss); //mm->total_vm;是进程虚拟内存的寻址空间大小 return mm->total_vm; }
上面的数值最后会通过 procfs输出 到/proc/$pid/statm中去,他们与top显示的数值对应关系如下
SHR: shared RES: resident VIRT: mm->total_vm CODE: code DATA: data /* [root@iZ23lobjjltZ ~]# cat /proc/434/statm 3160 195 99 18 0 113 0 */
0x1: 示例CODE
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/ipc.h> #include <sys/shm.h> #include <pthread.h> const int BUFF_SIZE = 1 << 23; const int SHARED_SIZE = 1 << 24; const int SHM_TEST_ID = 888; //4 static char GTestMem[1<<20]; //3 char GTestMem1[1<<20]; void TestMalloc() { //申请一段8M的栈空间 char szTemp[BUFF_SIZE]; //申请一段8M的堆空间 char* pszNew = (char*)malloc(BUFF_SIZE * sizeof(char)); if (pszNew == NULL) { printf("Malloc memory %d failed.\n", BUFF_SIZE); exit(-1); } //1 memset(szTemp, 'q', BUFF_SIZE); //1 memset(pszNew, 'w', BUFF_SIZE); //2 memset(szTemp, 'q', BUFF_SIZE / 4); //2 memset(pszNew, 'w', BUFF_SIZE / 4); while (1) { sleep(10); } } void ShMemory() { char szTemp[BUFF_SIZE]; char* pszNew = (char*)malloc(BUFF_SIZE * sizeof(char)); if (pszNew == NULL) { printf("Malloc memory %d failed.\n", BUFF_SIZE); exit(-1); } int fdShMem = shmget(SHM_TEST_ID, SHARED_SIZE, 0666|IPC_CREAT); if (fdShMem == -1) { printf("Create shared memory failed.\n"); exit(-1); } void* pSHM = shmat(fdShMem, NULL, 0); if ( (int)pSHM == -1) { printf("Attach shared memory failed.\n"); exit(-1); } memset(pSHM, 't', SHARED_SIZE / 4); while (1) { sleep(10); } } void MallocLeak() { char szTemp[BUFF_SIZE]; // for (int i = 0; i < BUFF_SIZE / 4; i++) // szTemp[i] = i % 255; sleep(30); char* pszNew = NULL; while (1) { pszNew = (char*)malloc(BUFF_SIZE * sizeof(char)); if (pszNew == NULL) { printf("Malloc memory %d failed.\n", BUFF_SIZE); exit(-1); } // memset(pszNew, 7, BUFF_SIZE / 4); // free(pszNew); sleep(5); } } int main(int argc, char* argv[]) { TestMalloc(); // ShMemory(); return 0; }
Relevant Link:
http://wenku.baidu.com/view/1cb3338683d049649b6658a3.html http://blog.csdn.net/u011547375/article/details/9851455
8. Glibc、Glibc运行时库内存池管理对进程内存使用统计情况的影响
在Linux下,进程使用C库进行内存申请、释放,Glibc在内部维护了一套内存池管理机制,接管了应用程序的内存申请/释放行为
Copyright (c) 2015 LittleHann All rights reserved