Linux内存管理学习笔记--物理内存分配

简介:

每次深入了解一个技术问题,随着挖据的深入,都发现其背后总非常深的背景知识,甚至需要深入到很多底层系统,这个过程有时会让自己迷失,会让自己忘了当初的目的。

前篇中介绍系统启动时内存的使用情况,本篇将介绍简要Linux如何接管主机的物理内存、组织内存,最后会较为详细的介绍Linux分配内存的一段代码。

前面说了,Linux MM系统细节非常多,自己在探究的时候,也是尝试尽量抓住主线,这里也只能抽取了一些“主线剧情”介绍,其中还可以扩展出很多细节,看客感兴趣可以自己深究,后续如果兴趣还在,我也还会继续写出来。内核版本如果没有特别说明,就是使用2.6.33版本。

1. 物理内存组织

先声明一下,这里说的Linux都是运行Intel X86架构的。从80386开始,为了更好支持内存管理、虚拟内存技术,x86架构开始支持处理器的分页模式(分页是基于分段)。系统将内存分为一个个固定大小的块,称作“page frames”,x86架构每一个“page frames”大小为4096字节。Linux中使用struct page结构来描述一个“page frames”【链接中给出了2.6.18内核下的Page结构】,一个Page结构对应了一个物理内存页。

在Linux中,所有的struct page对象都放在一个数组mem_map,mem_map每一个元素对应一个Page。

2. NUMA下的内存结构

在NUMA架构下,系统根据CPU的物理颗数,将内存分成对应的Node。例如,两颗物理CPU,16GB内存的硬件:系统则将内存分成两个8GB,分别分配给两颗CPU:

my111.cm3:/root>#numactl --hardware
available: 2 nodes (0-1)
node 0 size: 8065 MB
node 1 size: 8080 MB

每一个Node,系统又将其分为多个Zone,64位x86架构下(参考:8.1.5),分为两个ZONE_DMA(低16MB,)、ZONE_NORMAL(其余内存)。所以NUMA架构下的内存分配,也就是在各个zone分配内存。

3. 内存分配函数栈

从底层系统的角度,内存分配有如下函数(这里介绍的底层函数,和上层函数的关系,以后再介绍):

这里来调查一下函数alloc_pages都做了些什么,都调用了哪些函数:

free_area是一个底层保存空闲内存页的数组,有着特殊的结构,它也是内存分配Buddy system的核心变量。

4. get_page_from_freelist和zone_reclaim_mode

上面函数get_page_from_freelist【mm/page_alloc.c】通过遍历系统中各个zone,来寻找可用内存,根据Linux系统中zone_reclaim_mode的设置不同,遍历时的行为略有不同。zone_reclaim_mode是Linux中的一个可配置参数,为了解该参数如何影响内存分配,那就打开get_page_from_freelist的代码,仔细看看遍历各个zone的流程:

上面看到,zone_reclaim_mode非零时,如果某个zone内存不够,则会尝试出发一次内存回收工作(zone_reclaim),等于零时,则直接尝试写一个zone。

上面是2.6.33内核的代码流程图,2.6.18(RHEL5.4的内核)中则因为没有zcl相对简单一些:

流程图中可以看到,zone_reclaim_mode非零时,get_page_from_freelist【mm/page_alloc.c】函数中会调用zone_watermark_ok扫描free_area,如果当面有没有足够的可用内存,就会调用zone_reclaim【mm/vmscan.c】函数回收内存,zone_reclaim实际调用zone_reclaim【mm/vmscan.】收回内存。

最后

每次深入了解一个技术问题,随着挖据的深入,都发现其背后总非常深的背景知识,甚至需要深入到很多底层系统,这个过程有时会让自己迷失,会让自己忘了当初的目的。如果是Linux方面的技术问题,一般最后会收缩到“体系结构”、“Linux原理”和“算法”,这恰恰对应了计算机系考研时候的三门课程:体系结构、操作系统、和数据结构

目录
相关文章
|
5天前
|
缓存 Linux
linux 手动释放内存
在 Linux 系统中,内存管理通常自动处理,但业务繁忙时缓存占用过多可能导致内存不足,影响性能。此时可在业务闲时手动释放内存。
48 17
|
7天前
|
消息中间件 Linux
Linux:进程间通信(共享内存详细讲解以及小项目使用和相关指令、消息队列、信号量)
通过上述讲解和代码示例,您可以理解和实现Linux系统中的进程间通信机制,包括共享内存、消息队列和信号量。这些机制在实际开发中非常重要,能够提高系统的并发处理能力和数据通信效率。希望本文能为您的学习和开发提供实用的指导和帮助。
60 20
|
1月前
|
存储 监控 算法
Java内存管理深度剖析:从垃圾收集到内存泄漏的全面指南####
本文深入探讨了Java虚拟机(JVM)中的内存管理机制,特别是垃圾收集(GC)的工作原理及其调优策略。不同于传统的摘要概述,本文将通过实际案例分析,揭示内存泄漏的根源与预防措施,为开发者提供实战中的优化建议,旨在帮助读者构建高效、稳定的Java应用。 ####
44 8
|
1月前
|
算法 Linux
深入探索Linux内核的内存管理机制
本文旨在为读者提供对Linux操作系统内核中内存管理机制的深入理解。通过探讨Linux内核如何高效地分配、回收和优化内存资源,我们揭示了这一复杂系统背后的原理及其对系统性能的影响。不同于常规的摘要,本文将直接进入主题,不包含背景信息或研究目的等标准部分,而是专注于技术细节和实际操作。
|
2月前
|
存储 算法 安全
深入理解Linux内核的内存管理机制
本文旨在深入探讨Linux操作系统内核的内存管理机制,包括其设计理念、实现方式以及优化策略。通过详细分析Linux内核如何处理物理内存和虚拟内存,揭示了其在高效利用系统资源方面的卓越性能。文章还讨论了内存管理中的关键概念如分页、交换空间和内存映射等,并解释了这些机制如何协同工作以提供稳定可靠的内存服务。此外,本文也探讨了最新的Linux版本中引入的一些内存管理改进,以及它们对系统性能的影响。
|
2月前
|
缓存 Prometheus 监控
Elasticsearch集群JVM调优设置合适的堆内存大小
Elasticsearch集群JVM调优设置合适的堆内存大小
452 1
|
1月前
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
|
2月前
|
Java
JVM内存参数
-Xmx[]:堆空间最大内存 -Xms[]:堆空间最小内存,一般设置成跟堆空间最大内存一样的 -Xmn[]:新生代的最大内存 -xx[use 垃圾回收器名称]:指定垃圾回收器 -xss:设置单个线程栈大小 一般设堆空间为最大可用物理地址的百分之80
|
2月前
|
Java
JVM运行时数据区(内存结构)
1)虚拟机栈:每次调用方法都会在虚拟机栈中产生一个栈帧,每个栈帧中都有方法的参数、局部变量、方法出口等信息,方法执行完毕后释放栈帧 (2)本地方法栈:为native修饰的本地方法提供的空间,在HotSpot中与虚拟机合二为一 (3)程序计数器:保存指令执行的地址,方便线程切回后能继续执行代码
27 3
|
2月前
|
存储 缓存 监控
Elasticsearch集群JVM调优堆外内存
Elasticsearch集群JVM调优堆外内存
59 1