mm3

进程VMA

每一个进程都有0GB~3GB虚拟地址,内核虚拟地址只有一个3GB~4GB,如下:

      3GB~4GB              内核空间
     /     |    \
   /       |      \
---------------------------------------
0GB~3GB  0GB~3GB  0GB~3GB       用户空间

A进程    B进程     C进程

因此不同进程可以有相同虚拟地址,但是不同进程的页表不一样,所以相同虚拟地址映射到不同的物理地址中。

每一个进程的0GB~3GB虚拟地址,只是用某几段区域,不会全部使用完;一般有text 段、data 段、BSS 段、Heap 段、Stack 段等,每一段虚拟地址区域就是一个vma

将每一个进程的所有段通过链表方式进行连接,如下:

struct task_struct {
    struct mm_struct *mm
};

struct mm_struct {
    struct vm_area_struct * mmap;        /* list of VMAs */
};

struct vm_area_struct {
    unsigned long vm_start;        /* Our start address within vm_mm. */
    unsigned long vm_end;        /* The first byte after our end address

    /* linked list of VM areas per task, sorted by address */
    struct vm_area_struct *vm_next;
};

查看一个进程vma的分布情况:

page fault的可能性

  1. 访问没有VMA的非法区内存区域,应用程序出现segv

  2. heap区域vma(R+W权限),指向页表是R权限;因此第一次写操作时,发生page fault,申请一页内存,页表权限是R+W,此过程称为minor

  3. 代码段vma(R+X权限),执行W操作,权限不对,应用程序出现segv

  4. 代码段 vma(R+X权限),执行X操作,如果页表不存在,需要申请页,读出代码段,有会硬盘I/O操作,此过程称为major

进程内存消耗的4个概念:VSS、RSS、PSS和USS

VSS:虚拟内存占用空间,VMA大小

RSS:实际内存占用空间,私有数据+共享内存

PSS:实际内存占用空间,私有数据+共享内存/共享数量

USS:实际内存占用空间,私有数据

查看VSS/RSS/PSS/USS占用大小,如下:

内存泄露的界定方法?

原理:连续多点采样法,随着运行时间越久,进程使用内存越多

  1. 先用free命令判断系统是否内存泄露?

  2. 分别检查应用空间与内核空间是否内存泄露?

应用空间内存泄露检查步骤:

  • 连续多点采样后,USS560 -> 608 -> 644,判断应用空间内存泄露

  • 通过valgrind进行检测,能够精确定位哪一行源码发生内存泄露,如下:

或者通过asan进行检测,但是需要gcc版本大于等于8,能够精确定位哪一行源码发生内存泄露,如下:

内核空间内存泄露检查步骤:

  • 查看内核空间的内存实时情况,判断内核空间内存泄露

  • linux kernel启动中DEBUG_KMEMLEAK功能,进行定位哪里出现内存泄露

Last updated

Was this helpful?