深入了解Linux的内存地址空间分配 (linux 内存地址空间)

Linux是一款使用广泛的操作系统,在很多场景下都能够展现出其强大的性能。其中内存管理作为其重要组成部分之一,也是Linux能够高效运行的关键因素之一。在实际应用中,Linux的内存地址空间分配策略无疑是其中的一个方面,它能够决定操作系统的可靠性和内存使用率。接下来,我们将,帮助读者更好地理解Linux内存管理的实现原理。

1. 内核空间与用户空间

操作系统的内存地址空间一般被划分为内核空间和用户空间两个区域。用户空间是指给用户进程分配的内存空间,是进程运行时使用的主要区域,其地址空间通常从0开始。而内核空间则是一个专用的区域,为操作系统内核所使用。Linux内核空间的地址从0xC0000000开始,该空间被保护,并只能由内核访问。内核空间包含了整个内核代码和相关数据,包括系统调用表,设备驱动程序等系统程序。

在一个Linux系统中,内核空间与用户空间是完全隔离的,内核对用户进程的限制几乎没有任何限制。用户进程只能访问自己所拥有的内存空间,而内核空间的内容则完全无法访问。在需要访问内核空间中的数据或程序时,用户进程必须通过系统调用,由内核代表其完成特定的操作。

2. 内存地址空间分配方法

Linux的内存空间分配方法一般分为连续和离散两种。在连续分配中,操作系统通过分配一个连续的内存区域来满足进程的内存需求。而离散分配则是将进程的内存需求分散到物理内存中的不同位置。其中,连续分配是最常用的内存分配方式。当需要建立新的进程时,操作系统将先在进程地址空间中分配一个空间作为代码段、数据段和堆栈。

在Linux中,内存分配的主要实现函数是alloc_pages和get_free_pages。这两个函数分别用于分配具有特定参数的连续内存块和指定大小的内存块。此外,还有kmalloc函数,可以用来为内核分配连续的小内存块。这些函数都是通过使用伙伴算法和SLAB/SLUB算法来优化内存分配的效率和速度的。

3. 伙伴和SLAB/SLUB算法

伙伴算法是一种内存管理算法,它可以为需要内存的应用程序自动分配一些连续的内存空间。伙伴算法就是将连续的可用内存块划分为不同的大小等级,每个等级中的内存块大小是2的次幂,如2^0, 2^1, 2^2等等。当有一个请求分配内存时,伙伴算法会从对应大小的内存块链表中检查是否有足够大小的内存块可以分配。

SLAB/SLUB算法是另一种内存管理算法。SLAB是Linux专门为内核设计的内存分配器,而SLUB则是一种新的内存分配器,引入了SLAB上不能处理的一些机制。这两种算法都是基于内存池的概念,为用户和内核空间中的对象分配和释放内存。通过使用内存池和内存垃圾回收机制,可以帮助系统更好地管理内存资源。

4. 内核地址空间的映射

在Linux中,内核使用虚拟地址来访问其地址空间。当使用虚拟地址时,需要将其转换成物理地址。在物理存储器与虚拟地址之间建立映射的过程被称为内存管理单元(MMU)。MMU在物理内存和虚拟内存之间建立了一张映射表,用于将虚拟地址映射到物理地址。

在Linux中,由于内核空间是由内核使用的,因此映射表在内核初始化时已经被构建。在内核的逻辑地址空间中,内核空间突出了位于更高部分,并且具有系统映射的特殊属性。这些属性可用于访问系统调用、显存和一些硬件IO端口等系统资源。

以上就是Linux内存地址空间分配的相关知识点介绍。虽然内存管理对于普通用户来说可能不是一个常见的话题,但是对于开发者和系统管理员来说,深入了解Linux内存地址空间分配是非常必要的。这对于帮助他们更好地理解Linux系统的内部工作原理,优化系统性能有着重要的作用。因此,在实际应用中,我们应该注重优化内存管理以充分利用系统资源,提高应用程序的性能和可靠性。

相关问题拓展阅读:

Linux内存系统

——虚拟内存定义

All about Linux swap space

Linux将物理RAM (Random Access Memory) 划分为称为页面的内存块。交换是将一页内存复制到硬盘上的预配置空间(称为交换空间)以释放改内存页面上的过程。物理内存和交换空间的组合就是可用的虚拟内存量。

虚拟内存的那点事儿

进程是与其他进程共享CPU和内存资源的。为了有效的管理内历纯存并减少出错,现代操作系统提供了一种对主存的抽象概念,即:虚拟内存( Virtual Memory )。

虚拟内存为每个进程提供一个一致的,私有的地址空间,每个进程拥有一片连续完整的内存空间。

正如 所说,虚拟内存不只是“使用硬盘空间来扩展内存”的技术。

虚拟内存的重要意义是它定义了一个连续的虚拟地址空间,

使得程序编写难度降低。并且,

把内存扩展到硬盘空间只是使用虚拟内存的必然结果,虚拟内存空间会存在硬盘中,并且会被全部放入内存中缓冲(按需),有的操作系统还会在内存不够的情况下,将一进程的内存全部放入硬盘空间中,并在切换到进程时再从硬盘读取

(这也是Windows会经常假死的原因…)。

虚拟内存主要提供了如下三个重要的能力:

内存通常被组织为一个由M个连续的字节大小的单元组成的数组。每个字节都有一个唯迅烂氏一的物理地址 (Physical Address PA) ,作为到数组的索引。

CPU访问内存最简单直接的方法就是使用物理地址,这种寻址方式称为

物理寻址

现代计算机使用的是一种被称为虚拟寻址 (Virtual Addressing) 的寻址方式。

使用虚拟寻址,CPU需要将虚拟地址翻译成物理地址,这样才能访问到真实的物理内存。

虚拟寻址需要硬件与操作系统之间相互合作。

CPU中含有一个被称为内存管理单元 (Memory Management Unit,MMU) 的硬件,它的功能是将虚拟地址转换称为物理地址,MMU需要借助存放在内存中的 页表 来动态翻译虚拟地址,该页表由操作系统管理。

分页表是一种数据结构,它用于计算机操作系统中虚拟内存系统,其存储了虚拟地址到物理地址之间的映射。虚拟地址在访问进程中是唯一的,而物理地址在硬件(比如内存)中是唯一的。

在操作系统中使用

虚拟内存

,每个进程会认为使用一块大的连续的内存,事实上,每个进程的内存散布在

物理内存

的不同区域。或者可能被调出到备份存储中(一般是硬盘)。当一个进程请求自己的内存,操作系统负责把程序生成的虚拟地址,映射到实际存储的物理内存上。操作系统在

分页表

中存储虚拟地址到物理地址的映射。每个映射被称为

分页表项(page table entry ,PTE)

在一个简单的地址空间方案中,由虚拟地址寻址的页与物理内存中的帧之间的关系。物理内存可以包含属于许多进程的页。如果不经常使用,或者物理内存已满,可以将页面分页到磁盘。在上图中,并非所有页面都在物理内存中。

虚拟地址到物理地址的转换(即虚拟内存的管理)、内存保护、CPU高速缓存的控制。

现代的内存管理单元是以

的方式,分割虚拟地址空间(处理器使用的地址范围)的;页的大小是2的n次方,通常为几KB(字节)。地址尾部的n位(页大小的2的次方数)作为页内的偏移量保持不变。其余的地址位(address)为(虚拟)页号。

内存管理单元通常借助一种叫做转译旁观缓冲器(Translation Lookaside Buffer,TLB)和相联高速缓存来将虚拟页号转换为物理页号。当后备缓冲器中没有转换记录时,则使用一种较慢的机制,其中包括专用硬件的数据结构或软件辅助手段。这个数据结构称为

分页表

,页表中的数据叫做

分页表项

(page table entry PTE)。物理页号结合页偏移量便提供了完整的物理地址。

页表 或 转换后备缓冲器数据项应该包括的信息有:

有时候,TLB和PTE会

禁止对虚拟页访问

,这亩散可能是因为没有RAM与虚拟页相关联。如果是这种情况,MMU将向CPU发出页错误的信号,操作系统将进行处理,也许会寻找RAM的空白帧,同时建立一个新的PTE将之映射到所请求的虚拟地址。如果没有空闲的RAM,可能必须关闭一个已经存在的页面,使用一些替换算法,将之保存到磁盘中(这被称为页面调度)。

当需要将虚拟地址转换为物理地址时,首先搜索TLB,如果找到匹配(TLB)命中,则返回物理地址并继续存储器访问。然而,如果没有匹配(称为TLB未命中),则MMU或操作系统TLB未命中处理器通常会查找

页表

中的地址映射以查看是否存在映射(页面遍历),如果存在,则将其写回TLB(这必须完成,因为硬件通过虚拟存储器系统中的TLB访问存储器),并且重启错误指令(这也可以并行发生)。此后续转换找到TLB命中,并且内存访问将继续。

虚拟地址到物理地址的转换过程,如果虚拟内存不存在与TLB,转换会被重置并通过分页表和硬件寻找。

通常情况下,用于处理此中断的程序是操作系统的一部分。如果操作系统判断此次访问有效,那么

操作系统会尝试将相关的分页从硬盘上的虚拟内存文件调入内存。

而如果访问是不被允许的,那么操作系统通常会结束相关的进程。

虽然叫做“页缺失”错误,但实际上这并不一定是一种错误。而且这一机制是利用虚拟内存来增加程序可用内存空间。

发生这种情况的可能性:

当原程序再次需要该页内的数据时,如果这一页确实没有被分配出去,那么系统只需要重新为该页在MMU内注册映射即可。

操作系统需要:

硬性页缺失导致的性能损失是很大的。

另外,有些操作系统会将程序的一部分延迟到需要使用的时候再加载入内存执行,以此提升性能。这一特性也是通过捕获硬性页缺失达到的。

当硬性页缺失过于频繁发生时,称发生

系统颠簸。

具体动作与所使用的操作系统有关,比如Windows会使用异常机制向程序报告,而类Unix系统则使用信号机制。

尽管在整个运行过程中,程序引用不同的页面总数(也就是虚拟内存大小)可能超出了物理存储器(DRAM)总大小,但是程序常常在较小的活动页面上活动,这个叫做工作集或者常驻集。在工作集被缓存后,对它的反复调用会使程序命中提高,从而提高性能。

大部分的程序都可以在存储器获取数据和读取中达到稳定的状态,当程序达到稳定状态时,存储器的使用量通常都不会太大。虚拟内存虽然可以有效率控制存储器的使用,

但是大量的页缺失还是造成了系统迟缓的主要因素。

当工作集的大小超过物理存储器大小,程序将会发生一种不幸的情况,这种情况称为

“颠簸”

,页面将不停的写入、释放、读取,由于大量的丢失(而非命中)而损失极大性能。用户可以增加随机存取存储器的大小或是减少同时在系统里运行程序的数量来降低系统颠簸的记录。

推荐阅读:

操作系统–分页(一)

操作系统实现(二):分页和物理内存管理

linux下查看内存地址空间的分配

cat /proc/iomem

这个可以查看,但不太野帆详细!

cat /高脊敏proc/interrupts 是中断戚枝向量。

cat /proc/interrupts

如果仅仅是看分配的地址 这个就够了

ldd 是查看某个可执行二进制程序所使用到的动态库文件的吧?

ldd可以查看

关于linux 内存地址空间的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。


数据运维技术 » 深入了解Linux的内存地址空间分配 (linux 内存地址空间)