电子产业一站式赋能平台

PCB联盟网

搜索
查看: 172|回复: 0
收起左侧

图解Linux内存管理_整体架构

[复制链接]

625

主题

625

帖子

7918

积分

高级会员

Rank: 5Rank: 5

积分
7918
发表于 2024-6-13 11:50:00 | 显示全部楼层 |阅读模式
大家好,这里是物联网心球。
前面我们学习了很多Linux内存方面的知识,比如:虚拟地址空间,进程空间,内存映射,页表机制等,我们学了这么多知识,似乎对Linux内存似懂非懂,为什么会出现这样的问题?原因在于我们缺乏对物理内存的了解,由于缺乏物理内存管理相关的知识,我们对于内存管理没有形成体系,所以才会似懂非懂。

0a1tahs5cm364012509445.png

0a1tahs5cm364012509445.png


本文我们抛弃八股文的学习方式,以一种创新的方式来学习Linux内存管理,我们基于物理地址来学习Linux内存管理。

1.UMA和NUMA架构
UMA(Uniform Memory Access)和NUMA(Non-Uniform Memory Access)是两种不同的内存访问架构。
1.1 UMA架构
UMA是一种对称多处理(SMP)系统的内存访问架构,它指的是所有处理器对内存的访问具有相同的延迟。
在UMA系统中,所有处理器共享同一总线或交叉点,可以直接访问共享内存,这意味着无论哪个处理器访问内存,延迟都是相同的,UMA适用于小规模的多处理器系统。

y0wgehy5uzc64012509545.png

y0wgehy5uzc64012509545.png


1.2 NUMA架构
NUMA是一种非对称多处理(NUMA)系统的内存访问架构,它指的是不同处理器对内存的访问延迟可能不同。
在NUMA系统中,每个处理器都有自己的本地内存和本地内存控制器,可以更快地访问本地内存。
如果一个处理器要访问其他处理器的本地内存,需要通过QPI总线去访问,这样延迟就会增加。
NUMA适用于大规模的多处理器系统,NUMA架构将物理内存分为一个个内存节点,内存节点和内存节点之间的物理地址有可能是不连续的,同一内存节点物理内存物理地址是连续的。

azf3tofqdbl64012509645.png

azf3tofqdbl64012509645.png

小节:
  • 不管是UMA和NUMA架构,物理内存的物理地址都是唯一的。
  • UMA架构可以理解为NUMA架构的一个节点,是NUMA架构的一种特殊情况。

    2. 物理内存管理
    我们围绕物理地址来理解物理内存,物理内存管理其实是对物理地址的管理。
    2.1物理地址
    物理地址是物理内存中每个字节的身份信息,我们要对物理内存进行读写必须要知道物理地址,每块物理内存区域通过起始地址和大小表示,每个物理地址的用途从硬件诞生就已经确定下来,如下图:

    rs32baimazy64012509745.png

    rs32baimazy64012509745.png

    备注:图片来自《奔跑吧Linux内核卷1》
    我们明确了物理地址的作用后,Linux内存管理可以简化为物理地址管理,如何管理物理地址,我们将用到页机制。

    2.2 page有什么用?
    页机制的核心是页(page),page为物理内存管理的最小单位。
    如果每个物理地址我们都花精力去管理,管理成本会非常高,也非常不现实,所以需要一种高效且灵活的机制来管理物理地址,这种机制我们称为页机制。

    ehipmh4eetc64012509845.png

    ehipmh4eetc64012509845.png

    如上图,物理内存被划分成一个个固定大小的页,页的大小通常为4KB,Linux通过struct page结构体来表示一个物理页,struct page定义如下:

    zpzollk2gi464012509945.png

    zpzollk2gi464012509945.png

    struct page实际大小大概为40B,并没有4KB大小,所以struct page只是物理页的映射和描述,并不是实际的物理页。
    每一个物理页都有一个对应的页号,称为PFN,PFN和物理地址一样,同样是唯一的,通过PFN我们可以定位到物理页的首地址。

    2.3 page,PFN,物理地址之间的关系?
    (1)PFN和物理地址相互转换
    PFN和物理地址遵循一定的转换关系,转换公式如下:

    z11qusnmhob64012510046.png

    z11qusnmhob64012510046.png

    PFN转物理地址
    一个PFN对应4KB的内存,4KB为4096 Byte,PFN * 4096为PFN对应的物理页的首地址(物理地址),PFN * 4096 = PFN
    物理地址转PFN
    PFN = 物理地址 / 4096 = 物理地址 >> 12。
    (2)page和PFN相互转换
    page和PFN相互转换需要结合内存模型讨论。
    (3)page和物理地址转换
    page和物理地址转换,需要借助PFN完成,page和物理地址不能直接转换,需要先转换成PFN,再通过PFN完成转换。

    3.三种内存模型
    Linux内存模型分为:
  • 平坦内存模型(FLATMEM)
  • 非连续内存模型(DISCONTIGMEM)
  • 稀疏内存模型(SPARSEMEM)
    我们不要被这些高大上的名字吓住,其实这些内存模型都是通过数组实现,不同的内存模型对page的组织方式不同。

    3.1 平坦内存模型
    平坦内存模型是指在Linux操作系统中,物理内存被视为一个连续的、线性的地址空间,而不是分段或分页的方式,这种模型使得内存管理更加简单和高效。

    etzcxkpnn3l64012510146.png

    etzcxkpnn3l64012510146.png

    平坦内存模式采用struct pglist_data指针数组表示,每个数组元素都是一个struct pglist_data对象,struct pglist_data对象表示一个内存节点,内存节点就是我们前面讲到的NUMA架构内存节点,struct pglist_data对象有一个node_mem_map成员,该成员是一个struct page指针,指向一个页表。
    平坦内存模型page和PFN转换:

    yyx0udtrvrt64012510246.png

    yyx0udtrvrt64012510246.png

    平坦内存模式只有一个节点0,平坦内存模型物理起始地址偏移为0。
  • PFN转page
    PFN转page首先得找到页表起始地址,计算方式如下:
    struct page *mem_map = node_data[0]->node_mem_map;
    PFN和ARCH_PFN_OFFSET的差值为数组索引值,页表起始地址+数组索引值得到page地址。
  • page转PFN
    page地址和mem_map地址的差值为数组索引值,数组索引值+ARCH_PFN_OFFSET为PFN值。

    3.2 非连续内存模型
    不连续内存模型是指内存空间被分割成多个不连续的区域,每个区域具有不同的物理地址范围。
    不连续内存模型可以提供更灵活的内存管理方式,但也增加了程序设计和实现的复杂性。

    mha1o31oeyv64012510346.png

    mha1o31oeyv64012510346.png

    非连续内存模型和平坦内存模型都是采用struct pglist_data指针数组来实现,非连续内存模型通常来说有多个节点,每个节点之间的物理内存的物理地址不连续,平坦内存模型可以理解为一个节点的非连续内存模型。
    非连续内存模型和平坦内存模型page和PFN转换方式是一样的。

    非连续内存模型的mem_map和ARCH_PFN_OFFSET每个节点都不一样。

    3.3 稀疏内存模型
    稀疏内存模型是一种用于管理大容量内存的机制,它允许系统在物理内存不连续的情况下有效地使用内存空间。稀疏内存模型中,内存被划分为多个区域,每个区域可以包含不同数量的页框。
    稀疏内存模型的主要目的是解决内存碎片化的问题。在传统的连续内存模型中,当系统中有大量空闲页框但它们不连续时,无法有效利用这些内存空间,而稀疏内存模型通过将内存划分为多个区域,可以更灵活地管理内存碎片,从而提高内存利用率。
    稀疏内存模型的管理单位为mem_section,定义如下:

    es5d2th3cm164012510446.png

    es5d2th3cm164012510446.png

    section_mem_map为页表起始地址,一个struct mem_section代表一块连续的物理内存区域,每个mem_section都有一个对应的编号,通过section编号可以定位到对应的mem_section。

    5uvvl4zesc164012510546.png

    5uvvl4zesc164012510546.png

    稀疏内存模型page和PFN转换方式:

    5pfe1mjek1m64012510646.png

    5pfe1mjek1m64012510646.png

  • page转PFN
    struct page结构体flags成员记录了page的section编号,通过flags解析出section编号,再通过section编号定位到mem_section对象,mem_section对象成员section_mem_map为页表地址,page地址和section_mem_map之间的差值为PFN。
  • PFN转page
    通过PFN获取到section编号,通过section编号定位到mem_section对象,section_mem_map + PFN获取到page地址。

    4.总结
    Linux内存管理非常复杂,我们要掌握Linux内存管理,首先得了解页机制,通过页机制了解页,PFN,物理地址之间的关系,有了这个基础,我们再去学习Linux内存管理,我们的思路才会清晰。
  • 回复

    使用道具 举报

    发表回复

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条


    联系客服 关注微信 下载APP 返回顶部 返回列表