精确度量Linux下进程占用多少内存的方法

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云原生数据库 PolarDB 分布式版,标准版 2核8GB
简介: 在Linux中,要了解进程的信息,莫过于从 proc 文件系统中入手去看。proc的详细介绍,可以参考内核文档的解读,里面有很多内容 yum install -y kernel-doc cat /usr/share/doc/kernel-doc-3.10.0/Documentation/

在Linux中,要了解进程的信息,莫过于从 proc 文件系统中入手去看。
proc的详细介绍,可以参考内核文档的解读,里面有很多内容

yum install -y kernel-doc
cat /usr/share/doc/kernel-doc-3.10.0/Documentation/filesystems/proc.txt
AI 代码解读

主要内容

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
AI 代码解读

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

 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
AI 代码解读

详解

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)
AI 代码解读

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)
AI 代码解读

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.
AI 代码解读

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
AI 代码解读



一般来说,业务进程使用的内存主要有以下几种情况:
(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.  
AI 代码解读

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

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

Pss:                 374 kB
AI 代码解读

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

Private_Clean:         0 kB
Private_Dirty:         0 kB
AI 代码解读

在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.
AI 代码解读

例子

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_
AI 代码解读


其他参考文章

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
...
AI 代码解读

我拿 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).
AI 代码解读

简单一点说,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
AI 代码解读

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

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
AI 代码解读

一般来说,得出来的值,是和 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
AI 代码解读

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

据说是因为

VmSize = memory + memory-mapped hardware (e.g. video card memory).
AI 代码解读
目录
打赏
0
0
0
2
20693
分享
相关文章
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
在计算机系统的底层架构中,操作系统肩负着资源管理与任务调度的重任。当我们启动各类应用程序时,其背后复杂的运作机制便悄然展开。程序,作为静态的指令集合,如何在系统中实现动态执行?本文带你一探究竟!
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
从零开始掌握进程间通信:管道、信号、消息队列、共享内存大揭秘
本文详细介绍了进程间通信(IPC)的六种主要方式:管道、信号、消息队列、共享内存、信号量和套接字。每种方式都有其特点和适用场景,如管道适用于父子进程间的通信,消息队列能传递结构化数据,共享内存提供高速数据交换,信号量用于同步控制,套接字支持跨网络通信。通过对比和分析,帮助读者理解并选择合适的IPC机制,以提高系统性能和可靠性。
367 14
|
3月前
|
linux 手动释放内存
在 Linux 系统中,内存管理通常自动处理,但业务繁忙时缓存占用过多可能导致内存不足,影响性能。此时可在业务闲时手动释放内存。
166 17
|
15天前
|
Linux系统资源管理:多角度查看内存使用情况。
要知道,透过内存管理的窗口,我们可以洞察到Linux系统运行的真实身姿,如同解剖学家透过微观镜,洞察生命的奥秘。记住,不要惧怕那些高深的命令和参数,他们只是你掌握系统"魔法棒"的钥匙,熟练掌握后,你就可以骄傲地说:Linux,我来了!
92 27
|
9天前
|
如何创建Linux交换文件?Linux交换文件最新创建方法
Swap是Linux中的虚拟内存空间,用于在物理内存不足时将非活动进程移至磁盘,从而优化活动进程的性能。通过创建交换文件(如1GB),可灵活调整交换空间而无需重新分区。步骤包括:使用`fallocate`或`dd`创建文件、设置权限 (`chmod 600`)、格式化 (`mkswap`)、启用交换 (`swapon`)、修改`/etc/fstab`以持久化配置,以及调整`vm.swappiness`值(默认60,建议从10开始)来平衡内存与交换的使用。最后通过`swapon -s`检查状态并重启生效。此方法适用于VPS和专用服务器,需以root用户操作。
31 2
【YashanDB 知识库】如何避免 yasdb 进程被 Linux OOM Killer 杀掉
本文来自YashanDB官网,探讨Linux系统中OOM Killer对数据库服务器的影响及解决方法。当内存接近耗尽时,OOM Killer会杀死占用最多内存的进程,这可能导致数据库主进程被误杀。为避免此问题,可采取两种方法:一是在OS层面关闭OOM Killer,通过修改`/etc/sysctl.conf`文件并重启生效;二是豁免数据库进程,由数据库实例用户借助`sudo`权限调整`oom_score_adj`值。这些措施有助于保护数据库进程免受系统内存管理机制的影响。
【Linux】进程概念和进程状态
本文详细介绍了Linux系统中进程的核心概念与管理机制。从进程的定义出发,阐述了其作为操作系统资源管理的基本单位的重要性,并深入解析了task_struct结构体的内容及其在进程管理中的作用。同时,文章讲解了进程的基本操作(如获取PID、查看进程信息等)、父进程与子进程的关系(重点分析fork函数)、以及进程的三种主要状态(运行、阻塞、挂起)。此外,还探讨了Linux特有的进程状态表示和孤儿进程的处理方式。通过学习这些内容,读者可以更好地理解Linux进程的运行原理并优化系统性能。
38 4
Linux中的System V通信标准--共享内存、消息队列以及信号量
希望本文能帮助您更好地理解和应用System V IPC机制,构建高效的Linux应用程序。
144 48
【Linux】进程IO|系统调用|open|write|文件描述符fd|封装|理解一切皆文件
本文详细介绍了Linux中的进程IO与系统调用,包括 `open`、`write`、`read`和 `close`函数及其用法,解释了文件描述符(fd)的概念,并深入探讨了Linux中的“一切皆文件”思想。这种设计极大地简化了系统编程,使得处理不同类型的IO设备变得更加一致和简单。通过本文的学习,您应该能够更好地理解和应用Linux中的进程IO操作,提高系统编程的效率和能力。
105 34
|
1月前
|
Linux:守护进程(进程组、会话和守护进程)
守护进程在 Linux 系统中扮演着重要角色,通过后台执行关键任务和服务,确保系统的稳定运行。理解进程组和会话的概念,是正确创建和管理守护进程的基础。使用现代的 `systemd` 或传统的 `init.d` 方法,可以有效地管理守护进程,提升系统的可靠性和可维护性。希望本文能帮助读者深入理解并掌握 Linux 守护进程的相关知识。
56 7