Linux 内存分析——进程和物理结构角度

前言

关于 Linux 内存管理方面一些文章和书籍中都使用大量的篇幅去讲解,本篇文章主要从进程如何使用内存和物理内存如何管理的两个角度出发,去看 linux 系统是如何管理内存的。由于涉及的点比较多,并且本人技术水平有限,一些内容不会讲的太过深入,一些我比较感兴趣的点,我们会在后续文章中进一步学习。

进程如何使用内存

进程地址空间

所有进程的执行都需要占用一定的内存,那么进程是怎么使用机器上的内存的呢,linux 系统上每一个进程都有自己可以访问的内存地址空间,对应 4G(32位系统) 大小。第一部分为“用户空间”,用来映射其整个进程空间(0x0000 0000-0xBFFF FFFF)即3G字节的虚拟地址;第二部分为“内核空间”,用来映射(0xC000 0000-0xFFFF FFFF)1G字节的虚拟地址。可以看出Linux系统中每个进程的页面目录的第二部分是相同的,所以从进程的角度来看,每个进程有4G字节的虚拟空间, 较低的3G字节是自己的用户空间,最高的1G字节则为与所有进程以及内核共享的系统空间。4G 是进程认为的虚拟地址空间,一个进程实际占用的物理空间通过实际分配的计算。虚拟内存通过页表映射到物理内存,两个进程也可以通过映射到统一物理地址实现内存共享。

1-process-address

上图左边展示的是内核内存地址空间(1G),右边展示的是用户内存地址空间,每当进程切换用户空间就会跟着变化;而内核空间是由内核负责映射,它并不会跟着进程改变,是固定的,进程访问内核空间的方式:系统调用和中断。内核空间地址有自己对应的页表(init_mm.pgd),用户进程各自有不同的页表。

上图右边讲解了进程地址空间中使用的数据段种类:

  • 代码段(text):代码段是用来存放可执行文件的操作指令,也就是说是它是可执行程序在内存中的镜像。代码段需要防止在运行时被非法修改,所以只准许读取操作,而不允许写入(修改)操作——它是不可写的。
  • 数据段(data):数据段用来存放可执行文件中已初始化全局变量,换句话说就是存放程序静态分配的变量和全局变量。
  • BSS 段:BSS段包含了程序中未初始化的全局变量,在内存中 bss段全部置零。
  • 堆(heap):堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)
  • 栈(stack):栈是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。

虚拟内存在内核中的实现

进程在内核中以 task_struct 结构体表示,task_struct 中的 mm_struct 结构体用来存放进程地址空间的所有信息。虚拟内存的最小单位是 vma 结构体,其中每一块内存都通过 vm_area_struct 来存放。vma 中记录开始和结束位置,vma 成链表结构存放在 mm_struct 中,另外还有红黑树提供快速定位查找。如下图所示:
1-mm_struct

系统上查看进程内存

上面介绍了进程使用内存的一些理论,那么能否在系统上直观的看到进程使用了哪些内存呢? 通过/proc/PID/maps 或者 pmap 命令可以看到进程使用 VMA 映射了的内存区域和访问权限。通过/proc/PID/smaps 可以看到更详细的信息。

# pmap -x 5371
5371:   nginx: worker process                
Address           Kbytes     RSS   Dirty Mode   Mapping
0000000000400000     564     344       0 r-x--  nginx          //代码段
000000000068c000      68      68      60 rw---  nginx          //数据段
000000000069d000      56      12      12 rw---    [ anon ]
000000000a0c8000    1812    1684    1684 rw---    [ anon ]
0000003ac0a00000     112      40       0 r-x--  ld-2.5.so      //代码段
0000003ac0c1c000       4       4       4 r----  ld-2.5.so      //数据段
0000003ac0c1d000       4       4       4 rw---  ld-2.5.so      //bss 段
0000003ac0e00000    1340     284       0 r-x--  libc-2.5.so
0000003ac0f4f000    2044       0       0 -----  libc-2
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值