linux内存映射

简介:

  内存管理分为对连续物理内存区管理和非连续内存区管理,本文主要讲解连续的物理内存区管理的技术中所涉及到的内核线性地址空间映射的相关知识。涉及到的东西有:页框,管理区(高端内存,低端内存),高端内存映射等,这些知识是掌握伙伴系统算法和slab分配器的基础。

一、页框   

  页框为物理内存分配的基本单元,现代32位计算机一般设置为4KB(见上文计算机内存寻址)。内核必须记录每个页框的当前状态,例如:页框属于哪个经常的页,哪些页框抱哈的是内核代码或内核数据等,由此linux定义了一个页框的描述符:page。linux用page来保存页框的状态信息,所有的page都存放在mem_map数组中,以便管理内存。

二、管理区  

  很显然,如果计算机对内存的使用没有区别,那么直接使用页框管理内存是最为方便的。但是,由于计算机体系结构的的硬件限制:

  (1)ISA总线的直接内存存取(DMA)处理器只能对随机存储器(RAM)的前16MB寻址。

  (2)具有大容量的RAM的32位计算机中,CPU不能直接访问所有的物理内存!

  所以,由于上述的原因,Linux将物理内存划分为3个管理区:

  (1)ZONE_DMA:包含低于16M的内存页框,只有它能够作用于DMA;

  (2)ZONE_NORMAL:包含高于16M且低于896M的内存页框;

  (3)ZONE_HIGHMEM:包含从896M开始高于896M的内存页框。

  ZONE_DMA和ZONE_NORMAL我们一般称之为低端内存(896MB),ZONE_HIGHMEM称之为高端内存。高、低端内存的分类主要在于区分物理内存地址是否可以直接映射到内核线性地址空间中。问题来了,高、低端内存和内核的线性空间的映射是什么样的呢?

  在32位系统中,线性地址空间是4G,其中规定3~4G的范围是内核空间(1G),0~3G是用户空间(3G)。如果把这1G的内核线性地址空间全部拿来直接一一映射物理内存的话,在内核态的所有进程(线程)能使用的物理内存总共最多只有1G,很显然,如果你有4G内存,3G都不能用来做内核空间,太浪费了!

  为了能使在内核态的所有进程能使用更多的物理内存,linux采取了一种变通的形式:它将1G内核线性地址空间分为2部分,第一部分为1G的前896M,这部分内核线性空间与物理内存的0~896M一一映射,第二部分为1G的后128M的线性空间,拿来动态映射剩下的所有物理内存。

  看到这里应该几乎懂了为什么要有高端内存和低端内存的区分了!内核线性地址空间的前896M映射的就是我们的低端页框内存(ZONE_DMA和ZONG_NORMAL),而且是直接映射;内核线性地址空间的后128M映射的是我们的高端页框内存(ZONG_HIGHMEME)。

  上述的三个管理区,每个管理区都有自己的管理区描述符,管理区描述符的地址存放在zone_table数组中。内核调用一个内存分配函数时,必须指明请求页框所在的管理区。

  为满足内存分配请求,内存管理区使用两种方式来保证:

  (1)当空闲内存不足时,发出请求的内核控制路径阻塞,知道有内存释放,才分配。

  (2)如果内核控制路径不能被阻塞(原子内存分配请求),就从页框池中分配内存。

  页框池为内存保留的内存,由ZONE_DMA和ZONE_NORMAL来共同分配,分配的页框池大小为:sqrt(16*直接映射内存) KB

三、高端内存页框的内核映射

  在前面有提到,内核线性地址空间的最后128M用来映射高端内存页框,其方式有三种:永久内核映射,临时内核映射,非连续内存分配。由于本文只讲连续内存分配,最后一种映射方式就在下一篇blog中讲。

1、永久内核映射

  永久内核映射允许内核建立高端页框到内核地址空间的长期映射。他使用主内核页表中一个专门的页表,其页表地址存放在pkmap_page_table中,页表包含512项或1024项,因此,内核一次最多访问2M或4M的高端内存(地址范围是 4G-8M 到 4G-4M 之间,这个地址空间起叫“内核永久映射空间”或者“永久内核映射空间”)。

  永久内核映射通过kmap()函数建立,代码:

kmap()

  对于不使用的的 page,及应该时从这个空间释放掉(也就是解除映射关系),通过 kunmap() ,可以把一个 page 对应的线性地址从这个空间释放出来。

2、临时内核映射
  临时内核映射可用在中断处理程序和可延迟函数的内部,它从不阻塞当前进程。

  内核在 FIXADDR_START 到 FIXADDR_TOP 之间保留了一些线性空间用于特殊需求。这个空间称为“固定映射空间”,在这个空间中,有一部分用于高端内存的临时映射。这块空间具有如下特点:

  (1) 每个 CPU 占用一块空间;

  (2) 在每个 CPU 占用的那块空间中,又分为多个小空间,每个小空间大小是 1 个 page,每个小空间用于一个目的,这些目的定义在 kmap_types.h 中的km_type 中。

  当要进行一次临时映射的时候,需要指定映射的目的,根据映射目的,可以找到对应的小空间,然后把这个空间的地址作为映射地址。这意味着一次临时映射会导致以前的映射被覆盖。

  通过 kmap_atomic() 可实现临时映射。代码

 

kmap_atomic

 

 

 

 最后,给一张页框页管理区的图,加深内核线性地址空间映射的印象:

 

参考:

1、深入理解Linux内核

2、Linux 内存管理 -- 高端内存的映射方式 http://blog.csdn.net/chenziwen/article/details/5932396

3、Linux内核--内核地址空间分布和进程地址空间 http://www.360doc.com/content/12/1022/13/6828497_243054228.shtml

4、linux内存管理浅析 http://hi.baidu.com/_kouu/item/4c73532902a05299b73263d0

目录
相关文章
|
11天前
|
缓存 Linux
linux 手动释放内存
在 Linux 系统中,内存管理通常自动处理,但业务繁忙时缓存占用过多可能导致内存不足,影响性能。此时可在业务闲时手动释放内存。
64 17
|
2月前
|
监控 Linux
如何检查 Linux 内存使用量是否耗尽?这 5 个命令堪称绝了!
本文介绍了在Linux系统中检查内存使用情况的5个常用命令:`free`、`top`、`vmstat`、`pidstat` 和 `/proc/meminfo` 文件,帮助用户准确监控内存状态,确保系统稳定运行。
888 6
|
13天前
|
消息中间件 Linux
Linux:进程间通信(共享内存详细讲解以及小项目使用和相关指令、消息队列、信号量)
通过上述讲解和代码示例,您可以理解和实现Linux系统中的进程间通信机制,包括共享内存、消息队列和信号量。这些机制在实际开发中非常重要,能够提高系统的并发处理能力和数据通信效率。希望本文能为您的学习和开发提供实用的指导和帮助。
75 20
|
2月前
|
缓存 Java Linux
如何解决 Linux 系统中内存使用量耗尽的问题?
如何解决 Linux 系统中内存使用量耗尽的问题?
223 48
|
1月前
|
算法 Linux
深入探索Linux内核的内存管理机制
本文旨在为读者提供对Linux操作系统内核中内存管理机制的深入理解。通过探讨Linux内核如何高效地分配、回收和优化内存资源,我们揭示了这一复杂系统背后的原理及其对系统性能的影响。不同于常规的摘要,本文将直接进入主题,不包含背景信息或研究目的等标准部分,而是专注于技术细节和实际操作。
|
2月前
|
传感器 人工智能 物联网
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发,以及面临的挑战和未来趋势,旨在帮助读者深入了解并掌握这些关键技术。
72 6
|
2月前
|
缓存 Ubuntu Linux
Linux环境下测试服务器的DDR5内存性能
通过使用 `memtester`和 `sysbench`等工具,可以有效地测试Linux环境下服务器的DDR5内存性能。这些工具不仅可以评估内存的读写速度,还可以检测内存中的潜在问题,帮助确保系统的稳定性和性能。通过合理配置和使用这些工具,系统管理员可以深入了解服务器内存的性能状况,为系统优化提供数据支持。
68 4
|
2月前
|
Linux
如何在 Linux 系统中查看进程占用的内存?
如何在 Linux 系统中查看进程占用的内存?
|
2月前
|
缓存 Linux
如何检查 Linux 内存使用量是否耗尽?
何检查 Linux 内存使用量是否耗尽?
|
2月前
|
算法 Linux 开发者
深入探究Linux内核中的内存管理机制
本文旨在对Linux操作系统的内存管理机制进行深入分析,探讨其如何通过高效的内存分配和回收策略来优化系统性能。文章将详细介绍Linux内核中内存管理的关键技术点,包括物理内存与虚拟内存的映射、页面置换算法、以及内存碎片的处理方法等。通过对这些技术点的解析,本文旨在为读者提供一个清晰的Linux内存管理框架,帮助理解其在现代计算环境中的重要性和应用。