背景

在Linux中,要了解进程的信息,莫过于从 proc 文件系统中入手去看。

proc的详细介绍,可以参考内核文档的解读,里面有很多内容

yum install -y kernel-doc
cat /usr/share/doc/kernel-doc-3.10.0/Documentation/filesystems/proc.txt

proc主要内容

Table of Contents
----------------- 0 Preface
0.1 Introduction/Credits
0.2 Legal Stuff 1 Collecting System Information
1.1 Process-Specific Subdirectories
1.2 Kernel data
1.3 IDE devices in /proc/ide
1.4 Networking info in /proc/net
1.5 SCSI info
1.6 Parallel port info in /proc/parport
1.7 TTY info in /proc/tty
1.8 Miscellaneous kernel statistics in /proc/stat
1.9 Ext4 file system parameters 2 Modifying System Parameters 3 Per-Process Parameters
3.1 /proc/<pid>/oom_adj & /proc/<pid>/oom_score_adj - Adjust the oom-killer
score
3.2 /proc/<pid>/oom_score - Display current oom-killer score
3.3 /proc/<pid>/io - Display the IO accounting fields
3.4 /proc/<pid>/coredump_filter - Core dump filtering settings
3.5 /proc/<pid>/mountinfo - Information about mounts
3.6 /proc/<pid>/comm & /proc/<pid>/task/<tid>/comm
3.7 /proc/<pid>/task/<tid>/children - Information about task children
3.8 /proc/<pid>/fdinfo/<fd> - Information about opened file 4 Configuring procfs
4.1 Mount options

和进程内存相关的几个信息

 maps           Memory maps to executables and library files    (2.4)
statm Process memory status information
status Process status in human readable form
smaps a extension based on maps, showing the memory consumption of
each mapping and flags associated with it

详解

status

这里可以看到概貌的内存统计

程序启动后,进程的内存占用可能包括程序本身的空间,共享的内存空间,mmap,malloc 的等

 VmPeak                      peak virtual memory size
VmSize total program size
VmLck locked memory size
VmHWM peak resident set size ("high water mark")
VmRSS size of memory portions
VmData size of data, stack, and text segments
VmStk size of data, stack, and text segments
VmExe size of text segment
VmLib size of shared library code
VmPTE size of page table entries
VmSwap size of swap usage (the number of referred swapents)

statm

内存统计信息,单位为PAGE ,通过getconf可以获得操作系统的page大小

getconf PAGE_SIZE

 Field    Content
size total program size (pages) (same as VmSize in status)
resident size of memory portions (pages) (same as VmRSS in status)
shared number of pages that are shared (i.e. backed by a file)
trs number of pages that are 'code' (not including libs; broken,
includes data segment)
lrs number of pages of library (always 0 on 2.6)
drs number of pages of data/stack (including libs; broken,
includes library text)
dt number of dirty pages (always 0 on 2.6)

maps

进程与可执行程序或动态库文件相关的映射信息

address           perms offset  dev   inode      pathname  

08048000-08049000 r-xp 00000000 03:00 8312       /opt/test
08049000-0804a000 rw-p 00001000 03:00 8312 /opt/test
0804a000-0806b000 rw-p 00000000 00:00 0 [heap]
a7cb1000-a7cb2000 ---p 00000000 00:00 0
a7cb2000-a7eb2000 rw-p 00000000 00:00 0
a7eb2000-a7eb3000 ---p 00000000 00:00 0
a7eb3000-a7ed5000 rw-p 00000000 00:00 0 [stack:1001]
a7ed5000-a8008000 r-xp 00000000 03:00 4222 /lib/libc.so.6
a8008000-a800a000 r--p 00133000 03:00 4222 /lib/libc.so.6
a800a000-a800b000 rw-p 00135000 03:00 4222 /lib/libc.so.6
a800b000-a800e000 rw-p 00000000 00:00 0
a800e000-a8022000 r-xp 00000000 03:00 14462 /lib/libpthread.so.0
a8022000-a8023000 r--p 00013000 03:00 14462 /lib/libpthread.so.0
a8023000-a8024000 rw-p 00014000 03:00 14462 /lib/libpthread.so.0
a8024000-a8027000 rw-p 00000000 00:00 0
a8027000-a8043000 r-xp 00000000 03:00 8317 /lib/ld-linux.so.2
a8043000-a8044000 r--p 0001b000 03:00 8317 /lib/ld-linux.so.2
a8044000-a8045000 rw-p 0001c000 03:00 8317 /lib/ld-linux.so.2
aff35000-aff4a000 rw-p 00000000 00:00 0 [stack]
ffffe000-fffff000 r-xp 00000000 00:00 0 [vdso]

1. where "address" is the address space in the process that it occupies, "perms"

is a set of permissions:

 r = read
w = write
x = execute
s = shared
p = private (copy on write)

2. "offset" is the offset into the mapping,

3. "dev" is the device (major:minor),

4. "inode" is the inode on that device.

0 indicates that  no inode is associated with the memory region, as the case would be with BSS (uninitialized data).

5. The "pathname" shows the name associated file for this mapping.

If the mapping is not associated with a file:  

 [heap]                   = the heap of the program
[stack] = the stack of the main process
[stack:1001] = the stack of the thread with tid 1001
[vdso] = the "virtual dynamic shared object",
the kernel system call handler or if empty, the mapping is anonymous.

smaps

对应每个映射的内存开销详情

08048000-080bc000 r-xp 00000000 03:02 13130      /bin/bash
Size: 1084 kB
Rss: 892 kB
Pss: 374 kB
Shared_Clean: 892 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 892 kB
Anonymous: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 374 kB
VmFlags: rd ex mr mw me de 1. the size of the mapping(size),
2. the amount of the mapping that is currently resident in RAM (RSS),
3. the process' proportional share of this mapping (PSS),
4. the number of clean and dirty private pages in the mapping.
Note that even a page which is part of a MAP_SHARED mapping, but has only a single pte mapped,
i.e. is currently used by only one process, is accounted as private and not as shared.
5. "Referenced" indicates the amount of memory currently marked as referenced or accessed.
6. "Anonymous" shows the amount of memory that does not belong to any file.
Even a mapping associated with a file may contain anonymous pages:
when MAP_PRIVATE and a page is modified, the file page is replaced by a private anonymous copy.
7. "Swap" shows how much would-be-anonymous memory is also used, but out on
swap.
8. "VmFlags" field deserves a separate description.
This member represents the kernel flags associated with the particular virtual memory area in two letter encoded manner.
The codes are the following:
rd - readable
wr - writeable
ex - executable
sh - shared
mr - may read
mw - may write
me - may execute
ms - may share
gd - stack segment growns down
pf - pure PFN range
dw - disabled write to the mapped file
lo - pages are locked in memory
io - memory mapped I/O area
sr - sequential read advise provided
rr - random read advise provided
dc - do not copy area on fork
de - do not expand area on remapping
ac - area is accountable
nr - swap space is not reserved for the area
ht - area uses huge tlb pages
nl - non-linear mapping
ar - architecture specific flag
dd - do not include area into core dump
mm - mixed map area
hg - huge page advise flag
nh - no-huge page advise flag
mg - mergable advise flag

一般来说,业务进程使用的内存主要有以下几种情况:

(1)用户空间的匿名映射页(Anonymous pages in User Mode address spaces),比如调用malloc分配的内存,以及使用MAP_ANONYMOUS的mmap;当系统内存不够时,内核可以将这部分内存交换出去;

(2)用户空间的文件映射页(Mapped pages in User Mode address spaces),包含map file和map tmpfs;前者比如指定文件的mmap,后者比如IPC共享内存;当系统内存不够时,内核可以回收这些页,但回收之前可能需要与文件同步数据;

(3)文件缓存(page in page cache of disk file);发生在程序通过普通的read/write读写文件时,当系统内存不够时,内核可以回收这些页,但回收之前可能需要与文件同步数据;

(4)buffer pages,属于page cache;比如读取块设备文件。

进程RSS, 进程使用的所有物理内存(file_rss+anon_rss),即Anonymous pages+Mapped apges(包含共享内存)

Resident Set Size:
number of pages the process has in real memory.
This is just the pages which count toward text, data, or stack space.
This does not include pages which have not been demand-loaded in,
or which are swapped out.

显然如果把所有进程RSS的值相加,可能会超过实际的内存大小,原因是RSS统计存在一定的重复部分,例如在共享内存的计算方面,不同的进程会有重复的现象。

通过smaps可以非常方便的将重复的部分消除掉。

例如有多个进程加载了同样的库文件,那么会在这些进程间均摊这部分内存,均摊后的共享部分加上进程私有的内存记为Pss。

Pss:                 374 kB

私有的内存则在Private里面计算

Private_Clean:         0 kB
Private_Dirty: 0 kB

在linux中有一个工具叫smem,其实就是通过smaps来统计的。

PSS是Pss的相加

USS则是Private的相加

yum install -y smem smemstat  

smem can report proportional set size (PSS), which is a more meaningful representation of the amount of memory used by libraries and applications in a virtual memory system.  

Because large portions of physical memory are typically shared among multiple applications, the standard measure of memory usage known as resident set size (RSS) will significantly overestimate memory usage. PSS instead measures each application's "fair share" of each shared area to give a realistic measure.

例子

smem
PID User Command Swap USS PSS RSS
23716 digoal postgres: postgres postgres 0 4924 5387 7040 对应的RSS, PSS, USS分别等于以下相加.
# cat /proc/23716/smaps | grep Rss
# cat /proc/23716/smaps | grep Pss
# cat /proc/23716/smaps | grep Private_

其他参考文章

https://www.selenic.com/smem/

http://hustcat.github.io/memory-usage-in-process-and-cgroup/

http://blog.hellosa.org/2010/02/26/pmap-process-memory.html

首先 ps 看一下我的系统跑着哪些process

$ ps aux  

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
...
czbug 1980 0.0 1.7 180472 34416 ? Sl Feb25 0:01 /usr/bin/yakuake
...

我拿 yakuake 这个小程序作例子。

其中,关于内存的是 VSZ 和 RSS 这两个

man ps 看看它们的含义:

rss       RSS    resident set size, the non-swapped physical memory that a task has used (in kiloBytes). (alias rssize, rsz).  

vsz       VSZ    virtual memory size of the process in KiB (1024-byte units). Device mappings are currently excluded; this is subject to change. (alias vsize).

简单一点说,RSS 就是这个process 实际占用的物理内存,VSZ 就是process 的虚拟内存,就是process 现在没有使用但未来可能会分配的内存大小。

其实这里的ps 出来的结果,是有点不正确的,如果把所有程序的 RSS 加起来,恐怕比你的实际内存还要大呢。为什么呢??因为 ps 的结果,RSS 那部分,是包括共享内存的。这里我用 pmap 来看看。

$ pmap -d 1980  

1980:   /usr/bin/yakuake
Address Kbytes Mode Offset Device Mapping
00110000 2524 r-x-- 0000000000000000 008:00002 libkio.so.5.3.0
00387000 4 ----- 0000000000277000 008:00002 libkio.so.5.3.0
00388000 32 r---- 0000000000277000 008:00002 libkio.so.5.3.0
00390000 16 rw--- 000000000027f000 008:00002 libkio.so.5.3.0
00394000 444 r-x-- 0000000000000000 008:00002 libQtDBus.so.4.5.2
00403000 4 ----- 000000000006f000 008:00002 libQtDBus.so.4.5.2
00404000 4 r---- 000000000006f000 008:00002 libQtDBus.so.4.5.2
00405000 4 rw--- 0000000000070000 008:00002 libQtDBus.so.4.5.2
00407000 228 r-x-- 0000000000000000 008:00002 libkparts.so.4.3.0
00440000 8 r---- 0000000000039000 008:00002 libkparts.so.4.3.0
00442000 4 rw--- 000000000003b000 008:00002 libkparts.so.4.3.0
00443000 3552 r-x-- 0000000000000000 008:00002 libkdeui.so.5.3.0
007bb000 76 r---- 0000000000377000 008:00002 libkdeui.so.5.3.0
007ce000 24 rw--- 000000000038a000 008:00002 libkdeui.so.5.3.0
007d4000 4 rw--- 0000000000000000 000:00000 [ anon ]
....
mapped: 180472K writeable/private: 19208K shared: 20544K

我略去了一部分输出,都是差不多的,重点在最后那行输出。

linux 会把一些shared libraries 载入到内存中,在pmap 的输出中,这些shared libraries 的名字通常是 lib*.so 。如 libX11.so.6.2.0 。这个 libX11.so.6.2.0 会被很多process load 到自己的运行环境中,同时,ps 输出的RSS 结果中,每个process 都包含了这个libX11.so.6.2.0 ,而事实上它只被load 了一次,如果单纯把ps 的结果相加,这样就重复计算了。

而 pmap 的输出中,writeable/private: 19208K ,这个就是yakuake 这个程序真正占用的物理内存,不包含shared libraries 。在这里,它只有19208K,而ps 的RSS 是34416K。

我在看这方面的资料时,还看到一些关于virtual memory 的,再记录下。

以下两个命令均可查看 vmsize 。

$ cat /proc/<pid>/stat | awk '{print $23 / 1024}'
$ cat /proc/<pid>/status | grep -i vmsize

一般来说,得出来的值,是和 ps 的 VSZ 是一样的,但有一种情况例外,就是查看X server 的时候。

举个例:

$ ps aux|grep /usr/bin/X|grep -v grep | awk '{print $2}'   # 得出X server 的 pid   ...
1076 $ cat /proc/1076/stat | awk '{print $23 / 1024}'
139012 $ cat /proc/1076/status | grep -i vmsize
VmSize: 106516 kB

而 ps 的 VSZ 为 106516 ,与后者是一致的。

据说是因为

VmSize = memory + memory-mapped hardware (e.g. video card memory).

参考:https://github.com/digoal/blog/blob/master/201606/20160608_01.md

精确度量Linux下进程占用多少内存的方法的更多相关文章

  1. Linux下进程通信的八种方法

    Linux下进程通信的八种方法:管道(pipe),命名管道(FIFO),内存映射(mapped memeory),消息队列(message queue),共享内存(shared memory),信号量 ...

  2. 【转】Linux 下取进程占用 cpu/内存 最高的前10个进程

    # Linux 下 取进程占用 cpu 最高的前10个进程ps aux|head -1;ps aux|grep -v PID|sort -rn -k +3|head # linux 下 取进程占用内存 ...

  3. linux 下取进程占用 cpu/内存 最高的前10个进程

    linux下获取占用CPU资源最多的10个进程,可以使用如下命令组合: ;|head linux下获取占用内存资源最多的10个进程,可以使用如下命令组合: ;|head 命令组合解析(针对CPU的,M ...

  4. Linux下找出吃内存的方法总结

    Linux下查询进程占用的内存方法总结,假设现在有一个「php-cgi」的进程 ,进程id为「25282」. 现在想要查询该进程占用的内存大小.linux命令行下有很多的工具进行查看,现总结常见的几种 ...

  5. 查找linux下进程占用CPU过高的原因,以php-fpm为例

    很多时候,线上服务器的进程在某时间段内长时间占用CPU过高,为了优化,我们需要找出原因. 1.找出占用CPU最高的10个进程 ps aux | sort -k3nr | head -n 10 或查看占 ...

  6. linux 下 取进程占用内存(MEM)最高的前10个进程

    # linux 下 取进程占用 cpu 最高的前10个进程ps aux|head -1;ps aux|grep -v PID|sort -rn -k +3|head # linux 下 取进程占用内存 ...

  7. linux下查询进程占用的内存方法总结

    linux下查询进程占用的内存方法总结,假设现在有一个「php-cgi」的进程 ,进程id为「25282」.现在想要查询该进程占用的内存大小.linux命令行下有很多的工具进行查看,现总结常见的几种方 ...

  8. linux下获取占用CPU资源最多的10个进程

    linux下获取占用CPU资源最多的10个进程,可以使用如下命令组合: ps aux|head -1;ps aux|grep -v PID|sort -rn -k +3|head linux下获取占用 ...

  9. Linux下查看占用CPU资源最多的几个进程

    linux下获取占用CPU资源最多的10个进程: ps aux|head -1;ps aux|grep -v PID|sort -rn -k +3|head linux下获取占用内存资源最多的10个进 ...

随机推荐

  1. Linux运维笔记-日常操作命令总结(2)

    回想起来,从事linux运维工作已近5年之久了,日常工作中会用到很多常规命令,之前简单罗列了一些命令:http://www.cnblogs.com/kevingrace/p/5985486.html今 ...

  2. <a>标签中href="javascript:;"** 为什么 style不用src**

    &src/href <!--href 用于标示资源和文档关系,src 用于替换标签内容--> <img src="xxx.jpg"/> <sc ...

  3. Stanford Word Segmenter的特定领域训练

    有没有人自己训练过Stanford Word Segmenter分词器,因为我想做特定领域的分词,但在使用Stanford Word Segmenter分词的时候发现对于我想做的领域的一些词分词效果并 ...

  4. [BUAA软工]第二次博客作业---结对编程

    [BUAA软工]结对作业 项目 内容 这个作业属于哪个课程 北航软工 这个作业的要求在哪里 2019年软件工程基础-结对项目作业 我在这个课程的目标是 学习如何以团队的形式开发软件,提升个人软件开发能 ...

  5. Linux内核分析 笔记八 进程的切换和系统的一般执行过程 ——by王玥

    一.进程切换的关键代码switch_to的分析 (一)进程调度与进程调度的时机分析 1.不同类型的进程有不同的调度需求 第一种分类: I/O-bound:频繁地进行I/O,花费很多的时间等待I/O操作 ...

  6. 读书笔记(chapter4)

    进程调度 4.1多任务 1.多任务系统可以划分为:非抢占式多任务和抢占式多任务: (在此模式下,由调度程序来决定什么时候停止一个进程的运行,以便其他进程能够得到执行机会,这个动作叫抢占: 时间片实际上 ...

  7. eclipse新建maven项目,修改默认jdk版本

    我们新建maven项目,默认jdk版本是1.5,我们可以修改成我们想要的版本,有两种方法 1每个项目修改,在pom.xml添加 <build> <plugins> <!- ...

  8. java.lang.Exception: No tests found matching Method tes(com.bw.test.Testrefiect) from org.junit.vintage.engine.descriptor.RunnerRequest@3bfdc050 at org.junit.internal.requests.FilterRequest.getRunner

    junit   方法  没有加上注解  @Test java.lang.Exception: No tests found matching Method tes(com.bw.test.Testre ...

  9. TestNG—学习笔记2

    关于TestNG,也是一边学一边总结,对于TestNG和Junit的比较其实也没有什么意义,都是一种测试框架,都是为了应用而生的东西,没有必要说谁好谁不好了.用的熟练用的好就是真的好啊. 下面简单的总 ...

  10. [转帖]浅析java程序的执行过程

    浅析java程序的执行过程 转帖来源: https://www.cnblogs.com/wangjiming/p/10315983.html 之前学习过 这一块东西 但是感觉理解的不深刻. copy一 ...