Linux 内存管理
Linux 操作系统采?了哪种?式来管理内存呢?
在回答这个问题前,我们得先看看 Intel 处理器的发展历史。 早期 Intel 的处理器从 80286 开始使?的是段式内存管理。但是很快发现,光有段式内存管理?没有?式内存管理是不够的,这会使它的 X86 系列会失去市场的竞争?。因此,在不久以后的 80386 中就实现了对?式内存管理。也就是说,80386 除了完成并完善从 80286 开始的段式内存管理的同时还实现了?式内存管理。 但是这个 80386 的?式内存管理设计时,没有绕开段式内存管理,?是建?在段式内存管理的基础上,这就意味着,?式内存管理的作?是在由段式内存管理所映射?成的地址上再加上?层地址映射。 由于此时由段式内存管理映射?成的地址不再是“物理地址”了,Intel 就称之为“线性地址”(也称虚拟地址)。于是,段式内存管理先将逻辑地址映射成线性地址,然后再由?式内存管理将线性地址映射成物理地址。
这?说明下逻辑地址和线性地址: 程序所使?的地址,通常是没被段式内存管理映射的地址,称为逻辑地址; 通过段式内存管理映射的地址,称为线性地址,也叫虚拟地址;
逻辑地址是「段式内存管理」转换前的地址,线性地址则是「?式内存管理」转换前的地址。
Linux 内存主要采?的是?式内存管理,但同时也不可避免地涉及了段机制。
这主要是上? Intel 处理器发展历史导致的,因为 Intel X86 CPU ?律对程序中使?的地址先进?段式映射,然后才能进??式映射。既然 CPU 的硬件结构是这样,Linux 内核也只好服从 Intel 的选择。 但是事实上,Linux 内核所采取的办法是使段式映射的过程实际上不起什么作?。也就是说,“上有政策,下有对策”,若惹不起就躲着?。
Linux 系统中的每个段都是从 0 地址开始的整个 4GB 虚拟空间(32 位环境下),也就是所有的段的起始地址都是?样的。这意味着,Linux 系统中的代码,包括操作系统本身的代码和应?程序代码,所?对的地址空间都是线性地址空间(虚拟地址),这种做法相当于屏蔽了处理器中的逻辑地址概念,段只被?于访问控制和内存保护。
Linux 的虚拟地址空间是如何分布的?
在 Linux 操作系统中,虚拟地址空间的内部?被分为内核空间和?户空间两部分,不同位数的系统,地址空间的范围也不同。?如最常?的 32 位和 64 位系统,如下所示:
通过这?可以看出: 32 位系统的内核空间占? 1G ,位于最?处,剩下的 3G 是?户空间; 64 位系统的内核空间和?户空间都是 128T ,分别占据整个内存空间的最?和最低处,剩下的中间部分是未定义的。
再来说说,内核空间与?户空间的区别: 进程在?户态时,只能访问?户空间内存; 只有进?内核态后,才可以访问内核空间的内存;
虽然每个进程都各?有独?的虚拟内存,但是每个虚拟内存中的内核地址,其实关联的都是相同的物理内存。这样,进程切换到内核态后,就可以很?便地访问内核空间内存。
接下来,进?步了解虚拟空间的划分情况,?户空间和内核空间划分的?式是不同的,内核空间的分布情况就不多说了。
我们看看?户空间分布的情况,以 32 位系统为例,我画了?张图来表示它们的关系: 过这张图你可以看到,?户空间内存,从低到?分别是 7 种不同的内存段: 程序?件段,包括?进制可执?代码; 已初始化数据段,包括静态常量; 未初始化数据段,包括未初始化的静态变量; 堆段,包括动态分配的内存,从低地址开始向上增?; ?件映射段,包括动态库、共享内存等,从低地址开始向上增?(跟硬件和内核版本有关); 栈段,包括局部变量和函数调?的上下?等。栈的??是固定的,?般是 8 MB 。当然系统也提供了参数,以便我们?定义??;
在这 7 个内存段中,堆和?件映射段的内存是动态分配的。?如说,使? C 标准库的 malloc() 或者mmap() ,就可以分别在堆和?件映射段动态分配内存。
总结
为了在多进程环境下,使得进程之间的内存地址不受影响,相互隔离,于是操作系统就为每个进程独?分配?套虚拟地址空间,每个程序只关???的虚拟地址就可以,实际上?家的虚拟地址都是?样的,但分布到物理地址内存是不?样的。作为程序,也不?关?物理地址的事情。
每个进程都有??的虚拟空间,?物理内存只有?个,所以当启?了?量的进程,物理内存必然会很紧张,于是操作系统会通过内存交换技术,把不常使?的内存暂时存放到硬盘(换出),在需要的时候再装载回物理内存(换?)。 那既然有了虚拟地址空间,那必然要把虚拟地址「映射」到物理地址,这个事情通常由操作系统来维护。
那么对于虚拟地址与物理地址的映射关系,可以有分段和分?的?式,同时两者结合都是可以的。 内存分段是根据程序的逻辑?度,分成了栈段、堆段、数据段、代码段等,这样可以分离出不同属性的段,同时是?块连续的空间。但是每个段的??都不是统?的,这就会导致内存碎?和内存交换效率低的问题。
于是,就出现了内存分?,把虚拟空间和物理空间分成??固定的?,如在 Linux 系统中,每??的??为 4KB 。由于分了?后,就不会产?细?的内存碎?。同时在内存交换的时候,写?硬盘也就?个?或?个?,这就??提?了内存交换的效率。
再来,为了解决简单分?产?的?表过?的问题,就有了多级?表,它解决了空间上的问题,但这就会导致 CPU 在寻址的过程中,需要有很多层表参与,加?了时间上的开销。于是根据程序的局部性原理,在CPU 芯?中加?了 TLB,负责缓存最近常被访问的?表项,??提?了地址的转换速度。 Linux 系统主要采?了分?管理,但是由于 Intel 处理器的发展史,Linux 系统?法避免分段管理。于是Linux 就把所有段的基地址设为 0 ,也就意味着所有程序的地址空间都是线性地址空间(虚拟地址),相当于屏蔽了 CPU 逻辑地址的概念,所以段只被?于访问控制和内存保护。
另外,Linxu 系统中虚拟空间分布可分为?户态和内核态两部分,其中?户态的分布:代码段、全局变量、BSS、函数栈、堆内存、映射区。
学自小林coding,侵删
|