Linux中内存管理的案例分析

  介绍

小编给大家分享一下Linux中内存管理的案例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获、下面让我们一起去了解一下吧!

在Linux下,使用,vmstat,自由等命令查看系统或者进程的内存使用情况时,经常看到浅黄色/缓存存储器,交换,利用Mem等,他们都代表什么意思呢?这篇文章将来聊一聊Linux下的内存管理并解答这个问题。

讨论Linux下的内存管理其实就是讨论Linux下虚拟内存的实现方式,本人不是内核专家,所以这篇文章只会介绍一些概念性的东西,不会深入实现细节,有些地方描述的有可能不精确。

在早些时候,物理内存比较有限,人们希望程序可以使用的内存空间能超过实际物理内存,于是出现了虚拟内存的概念,不过随着时间的推移,虚拟内存的意义已经远远的超过了最初的想法。

<强>

虚拟内存是Linux管理内存的一种技术。它使得每个应用程序都认为自己拥有独立且连续的可用的内存空间(一段连续完整的地址空间),而实际上,它通常是被映射到多个物理内存段,还有部分暂时存储在外部磁盘存储器上,在需要时再加载到内存中来。

每个进程所能使用的虚拟地址大小和CPU位数有关,在32位的系统上,虚拟地址空间大小是4 g,在64位系统上,是2 ^ 64=?(算不过来了)。而实际的物理内存可能远远小于虚拟地址空间的大小。

虚拟地址和进程息息相关,不同进程里的同一个虚拟地址指向的物理地址不一定一样,所以离开进程谈虚拟地址没有任何意义。

注意:网上很多文章将虚拟内存等同于交换空间,其实描述不够严谨,交换空间只是虚拟内存这张大蓝图中的一部分。

下面这张表很直观的表述了它们之间的关系

进程X进程Y   + - - - - - - - - - - - - - - + + +   | VPFN7 | - + | VPFN7 |   + - - - - - - - + |进程X的进程Y的+ - - - - - - - +   | VPFN6 | |页表页表+ - | VPFN6 |   + - - - - - - - - - - - - - | + + + - - - - - - - - - - - - - | + +   | VPFN5 | + - - - - -→| ....| - - - - - - + + - - - - - - - | ....| & lt; - - - - - - + | | VPFN5 |   + - - - - - - - - - - - - - + + + | + | + - - - - - - - - - - - - + + | | + - - - - - - - +   | VPFN4 | +——→| ....| - - - - - - + - + | PFN4 | | | ....| | | | VPFN4 |   + - - - - - - - - - - - - - | + + | | + | + - - - - - - - - - - - - + + | | + - - - - - - - +   | VPFN3 | - + | | ....| | | +——→| PFN3 | & lt; - - - - - - + + - - - - - | ....| & lt; - - - - - - + - + | VPFN3 |   + - - - - - - - + | | +——+ | | | +——+ | + | + - - - - - - - - - - - - - + +   | VPFN2 | + - + -→| ....| - - - - - - + - + - + | PFN2 | & lt; - - - - - - + | ....| | | VPFN2 |   + - - - - - - - - - - - - - | + + | | +——+ + + - - - - - - - - - - - - - | + +   | VPFN1 | | | + - - - - -→| FPN1 | + - - - - - | VPFN1 |   + - - - - - - - + | | + + - - - - - - - - - - - - - + +   | VPFN0 | - - - - - + + - - - - - -→| PFN0 | | VPFN0 |   + - - - - - - - + + - - - - - - - - - - - - - + + +   虚拟内存物理内存虚拟内存         PFN(页框号):页编号

当进程执行一个程序时,需要先从先内存中读取该进程的指令,然后执行,获取指令时用到的就是虚拟地址,这个地址是程序链接时确定的(内核加载并初始化进程时会调整动态库的地址范围),为了获取到实际的数据,CPU需要将虚拟地址转换成物理地址,CPU转换地址时需要用到进程的页表,而页表里面的数据由操作系统维护。

注意:Linux内核代码访问内存时用的都是实际的物理地址,所以不存在虚拟地址到物理地址的转换,只有应用层程序才需要。

为了转换方便,Linux将虚拟内存和物理内存都拆分为固定大小的页,x86的系统一般内存页大小是4 k,每个页都会分配一个唯一的编的号,这就是页编号(PFN)。

从上面的图中可以看的出,虚拟内存和物理内存的页面之间通过页表进行映射。进程X和Y的虚拟内存是相互独立的,且页表也是独立的,它们之间共享物理内存。进程可以随便访问自己的虚拟地址空间,而页表和物理内存由内核维护。当进程需要访问内存时,CPU会根据进程的页表将虚拟地址翻译成物理地址,然后进行访问。

注意:并不是每个虚拟地址空间的页面都有对应的页表相关联,只有虚拟地址被分配给进程后,也即进程调用类似malloc函数之后,系统才会为相应的虚拟地址在页表中添加记录,如果进程访问一个没有和页表关联的虚拟地址,系统将会抛出SIGSEGV信号,导致进程退出,这也是为什么我们访问野指针时会经常出现segmentfault的原因。换句话说,虽然每个进程都有4 g(32位系统)的虚拟地址空间,但只有向系统申请了的那些地址空间才能用,访问未分配的地址空间将会出segmentfault错误.Linux会将虚拟地址0不映射到任何地方,这样我们访问空指针就一定会报segmentfault错误。

Linux中内存管理的案例分析