1351|7

6386

帖子

8

TA的资源

管理员

楼主
 

阅读打卡第四站: 物理内存与虚拟内存 ——《奔跑吧Linux内核(第2版)卷1》 [复制链接]

>>点此进入阅读打卡总站,查看所有打卡题目

 

阅读小伙伴们,第四站打卡 题目开启:@paope    、@费炜 @lemonboard @chejia12 @maskmoo @硬核王同学 @小默叔叔 @yin_wu_qing @meiyao

预计阅读完《奔跑吧Linux内核(第2版)卷1:基础架构》第四章可解答。

作者笨叔给了的本章打卡题目:

1.请简述Linux内核在理想情况下页面分配器(page allocator)是如何分配出连续物理页面的。
2.在页面分配器中,如何从分配掩码(gfp_mask)中确定可以从哪些zone中分配内存?
3.页面分配器是按照什么方向来扫描zone的?
4.为用户进程分配物理内存时,分配掩码应该选用GFP_KERNEL,还是GFP_HIGHUSER_ MOVABLE呢?

 

 

论坛有开设嵌入式交流群,欢迎感兴趣的小伙伴,微信添加“helloeeworld”为好友,对话:加入嵌入式交流群,入群交流。

扫码,对话:加入嵌入式交流群。

加EE小助手好友,
入技术交流群
EE服务号
精彩活动e手掌握
EE订阅号
热门资讯e网打尽
聚焦汽车电子软硬件开发
认真关注技术本身

最新回复

1. 在理想情况下,alloc_pages()函数在伙伴系统能分配的最大内存块约为4MB大小; 2. gfp_mask的低4位来表示。对应ZONE_DMA中分配内存,ZONE_DMA32中分配内存。优先从ZONE_HIGHMEM分配。 3. 使用zonelist,所有可用zone的链表 4. 使用GFP_HIGHUSER_MOVABLE,其为用户空间进程分配内存。具体讲,优先使用高端内存,并且分配的内存具有可移动属性。   详情 回复 发表于 2023-12-27 18:36
点赞 关注
个人签名微信搜索公众号“EEWORLDBBS”快去添加关注吧!

回复
举报

5

帖子

0

TA的资源

一粒金砂(中级)

沙发
 
1、在理想情况下,Linux内核的页面分配器(page allocator)会使用伙伴系统(buddy system)算法来分配连续的物理页面。该算法将可用的物理页面划分为不同的大小类别,每个大小类别都是2的幂次方大小的页面块。例如,大小为2的幂次方的页面块可以是4KB、8KB、16KB等。当需要分配一段连续的物理页面时,页面分配器会从相应的大小类别中选择一个大小最接近需求大小的页面块,并将其分裂成两个较小的页面块,直到得到所需大小的页面块。如果没有足够大的页面块可用,则页面分配器会尝试从更大的页面块中分裂出所需大小的页面块。一旦找到了适当大小的页面块,页面分配器会将其标记为已分配,并返回其物理地址给调用者。此外,页面分配器还会跟踪已分配和未分配的页面块,以便在需要时快速找到可用的页面块。 2、在Linux内核的页面分配器中,分配掩码(gfp_mask)是一个用于指定分配内存时所需选项的掩码。其中包括了一些标志位,用于指示内存分配的要求和限制,例如分配的大小、分配的优先级等等。     在确定可以从哪些zone中分配内存时,页面分配器会根据gfp_mask中的标志位来进行判断。具体来说,它会检查以下标志位: __GFP_DMA:表示分配的内存需要在DMA区域中,即物理地址小于等于0x1000000(16MB)。 __GFP_HIGHMEM:表示分配的内存可以在HIGHMEM区域中,即物理地址大于0x1000000(16MB)。 __GFP_MOVABLE:表示分配的内存可以被移动,即不是永久性的内存分配,而是可以在需要时被移动。 __GFP_THISNODE:表示分配的内存必须在当前节点上分配,即不能跨节点分配内存。 __GFP_OTHER_NODE:表示分配的内存可以在其他节点上分配。根据gfp_mask中的标志位,页面分配器会决定从哪些zone中分配内存。     例如,如果gfp_mask包含__GFP_DMA标志位,则页面分配器只会从DMA zone中分配内存,而不会从HIGHMEM zone中分配内存。如果gfp_mask包含__GFP_MOVABLE标志位,则页面分配器会优先从MOVABLE zone中分配内存,而不会从不可移动的zone中分配内存。 3、在Linux内核中,页面分配器是按照以下顺序来扫描zone的: 当前节点的本地zone:首先,页面分配器会尝试从当前节点的本地zone中分配内存。本地zone是指与当前CPU所在节点相对应的zone,因为在同一节点上的内存分配速度比跨节点的内存分配速度更快。 当前节点的其他zone:如果当前节点的本地zone无法满足分配请求,页面分配器会尝试从当前节点的其他zone中分配内存。这些zone包括DMA、NORMAL、HIGHMEM等。 其他节点的本地zone:如果当前节点的所有zone都无法满足分配请求,页面分配器会尝试从其他节点的本地zone中分配内存。这些zone与当前CPU所在节点不同,但它们与请求分配内存的设备在同一节点上,因此分配速度也比跨节点的内存分配速度更快。 其他节点的其他zone:如果前面的所有zone都无法满足分配请求,页面分配器会尝试从其他节点的其他zone中分配内存。这些zone与当前CPU所在节点不同,并且它们与请求分配内存的设备也不在同一节点上,因此分配速度最慢。     需要注意的是,页面分配器在扫描zone时,会根据请求的分配大小和分配掩码(gfp_mask)来确定从哪些zone中分配内存。具体来说,它会根据gfp_mask中的标志位来过滤掉一些不符合要求的zone,例如__GFP_DMA标志位表示只从DMA zone中分配内存,__GFP_HIGHMEM标志位表示只从HIGHMEM zone中分配内存等等。 4、当为用户进程分配物理内存时,应该根据具体情况选择分配掩码。     一般情况下,如果分配的内存是用于进程自身的数据结构或者堆栈,那么应该选择GFP_KERNEL分配掩码。这是因为GFP_KERNEL分配掩码表示分配的内存可以被内核长期持有,不需要在内核和用户空间之间移动,因此适用于内核自身使用的内存。     如果分配的内存是用于用户进程的内存映射,那么应该选择GFP_HIGHUSER_MOVABLE分配掩码。这是因为GFP_HIGHUSER_MOVABLE分配掩码表示分配的内存可以在内核和用户空间之间移动,因此适用于用户进程使用的内存。此外,GFP_HIGHUSER_MOVABLE还表示分配的内存可以被移动到高端内存(HIGHMEM)中,这是一种物理内存不够用时的备选方案。     需要注意的是,GFP_HIGHUSER_MOVABLE分配掩码只适用于Linux内核2.6.16及以上版本。在早期版本的内核中,可以使用GFP_USER分配掩码来分配用户进程的内存映射。但是,GFP_USER分配掩码不支持内存移动,因此不适用于物理内存不够用时的情况。
 
 

回复

19

帖子

0

TA的资源

一粒金砂(中级)

板凳
 
 
 
 

回复

208

帖子

1

TA的资源

一粒金砂(高级)

4
 

1,在理想情况下,Linux内核的页面分配器会使用伙伴系统算法来分配连续的物理页面。这算法将可用内存划分为不同大小的块,并使用二进制树来跟踪可用和已分配的块。当请求分配连续页面时,分配器会搜索合适大小的块,然后通过合并操作来获得所需大小的连续页面。分配连续物理页面调用alloc_pages函数,alloc_pages函数包含两个参数,1. 分配掩码,2. 伙伴系统的order。分配掩码又分为zone的修饰符和action修饰符,前者确定可以优先从哪个zone开始扫描,后者确定物理页面的迁移类型。根据得到的zone的序号/action/order,三个值,确定了分配的路径。如果在指定的zone/迁移类型/order上分配不到连续的物理页面,则会考虑从不同的zone,不同的迁移类型和不同的order去分配物理页面。

2,分配掩码是一个标志位掩码,它包含了关于内存分配的各种选项,主要用于表示应当从哪些内存管理区中来分配物理内存。其中包括GFP_DMA、GFP_HIGHMEM、_GFP_DMA32等标志,它们用于指示内核在哪些内存区域中进行分配。例如,GFP_DMA表示应该从DMA区域分配内存,而GFP_HIGHMEM表示应该从高端内存区域分配内存。通过检查分配掩码中的这些标志位,页面分配器可以确定从哪些zone中分配内存。
3,一般优先从high -> normal->DMA32->DMA 这个顺序分配
4,选择GFP_HIGHUSER_MOVABLE。因为GFP_KERNEL是内核分配的常用标志之一,可能会被阻塞,即分配过程可能会睡眠,在中断上下文和并不能睡眠的内核路径使用该类型的标志需要特别警惕,可能会引起死锁或者其他系统异常;GFP_HIGHUSER_MOVABLE是为用户空间用来分配内存,页面可以迁移,优先使用高端内存并且分配的内存具有可移动的属性。

 
 
 

回复

66

帖子

0

TA的资源

一粒金砂(高级)

5
 

页面分配器如何工作:
当程序需要内存时,会请求一块连续的物理页面。Linux内核使用伙伴系统来管理这个任务。它会把可用的内存分成不同大小的块,并维护一个列表来记录哪些块是空闲的。当用户程序请求内存时,内核会在这个列表中找到一个足够大的块来满足请求。
分配掩码 gfp_mask 如何影响内存分配的区域:
分配掩码 gfp_mask 包含一些标志,描述了页面的分配方法,告诉内核如何处理内存请求。例如如果设置了 __GFP_DMA 标志,表示只能从DMA区域分配内存。通过设置不同的标志可以控制内核从哪个内存区域分配内存。
页面分配器扫描内存区域的方向:
通常会按照从低地址到高地址的方向进行。因为伙伴系统算法更倾向于在低地址处分配内存,这样可以更有效地利用内存,提高性能。
为用户进程选择分配掩码的建议:
当内核为用户进程分配物理内存时,建议使用 GFP_HIGHUSER_MOVABLE 而不是 GFP_KERNEL。这个标志表示内核会尽量从ZONE_HIGHUSER分配,并标记这些页为可移动的。这对于处理内存压力更友好,因为它允许系统更灵活地管理内存。

 
 
 

回复

64

帖子

0

TA的资源

一粒金砂(中级)

6
 
本帖最后由 硬核王同学 于 2023-12-24 23:05 编辑

1.请简述Linux内核在理想情况下页面分配器(page allocator)是如何分配出连续物理页面的。

答:在理想情况下,Linux内核的页面分配器会使用伙伴系统算法来分配连续的物理页面。这算法将可用内存划分为不同大小的块,并使用二进制树来跟踪可用和已分配的块。当请求分配连续页面时,分配器会搜索合适大小的块,然后通过合并操作来获得所需大小的连续页面。内核中分配物理内存页面的常用接口函数是alloc_pages(),它用于分配一个或者多个连续的物理页面,分配的页面个数只能是2的整数次幂。它的参数有两个,gfp_mask表示分配掩码,order表示分配级数。


2.在页面分配器中,如何从分配掩码(gfp_mask)中确定可以从哪些zone中分配内存?

答:分配掩码其实被定义成一个unsigned类型的变量。它被定义在include/linux/gfp.h文件中,它包含了关于内存管理区修饰符的标志,主要用于表示应当从哪些内存管理区中来分配物理内存。内存管理区修饰符使用gfp_mask的低4位来表示,其中包括GFP_DMA、GFP_HIGHMEM、_GFP_DMA32等标志,它们用于指示内核在哪些内存区域中进行分配。例如,GFP_DMA表示应该从DMA区域分配内存,而GFP_HIGHMEM表示应该从高端内存区域分配内存。通过检查分配掩码中的这些标志位,页面分配器可以确定从哪些zone中分配内存。


3.页面分配器是按照什么方向来扫描zone的?

答:Linux内核的页面分配器(buddy allocator)通常是按照从高到低的内存地址进行扫描。


4.为用户进程分配物理内存时,分配掩码应该选用GFP_KERNEL,还是GFP_HIGHUSER_ MOVABLE呢?

答:当为用户进程分配物理内存时,通常应该选择GFP_KERNEL分配掩码。

GFP_KERNEL是Linux内核中最常用的分配掩码,它用于分配内核空间中的内存。用户进程在运行时一般在内核空间中执行,因此使用GFP_KERNEL可以确保分配的内存位于内核空间中,可以直接访问和使用。

另一方面,GFP_HIGHUSER_ MOVABLE则是用于分配高端用户空间中的可移动内存。高端用户空间是指进程虚拟地址的较高部分,用于分配大于1GB的用户进程内存。GFP_HIGHUSER_ MOVABLE用于分配可通过move_pages接口移动的内存,这对于某些需要内存迁移功能的特殊应用情况可能有用,例如在NUMA系统中优化内存访问。

总之,对于大多数普通用户进程来说,应该使用GFP_KERNEL分配掩码来分配内存。只有在需要特殊的内存迁移功能或者高端用户空间时,才需要考虑使用GFP_HIGHUSER_ MOVABLE。对于大多数常规用户进程,GFP_KERNEL通常是最合适的选择。

 
 
 

回复

221

帖子

0

TA的资源

一粒金砂(高级)

7
 
  1. 请简述Linux内核在理想情况下页面分配器(page allocator)是如何分配出连续物理页面的。
    内核中分配物理内存页面的常用的接口函数是alloc_pages(),它用于分配一个或者多个连续的物理页面,分配的页面个数只能是2的整数次幂。想比于多次分配离散的物理页面,分配连续的物理页面有利于缓解系统内存的碎片化问题,内存碎片化是一个很让人头疼的问题。
    alloc_pages()函数的参数有两个,gfp_mask表示分配掩码,order表示分配级数。分配掩码又分为zone的修饰符和action修饰符,zone修饰符确定可以优先从哪个zone开始扫描,action修饰符确定物理页面的迁移类型。根据得到的zone的序号/action/order三个值,确定了分配的路径。如果在指定的zone/迁移类型/order上分配不到连续的物理页面,则会考虑从不同的zone,不同的迁移类型和不同的order去分配物理页面。
  2. 在页面分配器中,如何从分配掩码(gfp_mask)中确定可以从哪些zone中分配内存?
    内存管理区修饰符使用gfp_mask的低4位来表示。__GFP_DMA:从ZONE_DMA中分配内存,__GFP_DMA32:从ZONE_DMA32中分配内存,__GFP_HIGHMEM:优先从ZONE_HIGHMEM中分配内存,__GFP_MOVABLE:页面可以被拆迁移或者回收,如用于内存规整机制。一般优先从HIGHMEM -> MOVABLE ->DMA32->DMA这个顺序分配。
  3. 页面分配器是按照什么方向来扫描zone的?
    ZONE_HIGHMEM是分配器的首选zone,而ZONE_NORMAL是备选zone,在for_each_zone_zonelist_nodemask()函数中,next_zones_zonelist(++z,highidx,nodemask)依然会返回ZONE_NORMAL。因此这里会遍历ZONE_HIGHMEM和ZONE_NORMAL这两个ZONE,但是会先遍历ZONE_HIGHMEM,后遍历ZONE_NORMAL。
  4. 为用户进程分配物理内存时,分配掩码应该选用GFP_KERNEL,还是GFP_HIGHUSER_ MOVABLE呢?
        GFP_KERNEL主要用于分配内核使用的内存,在分配过程中会引起睡眠,在中断上下文和不能睡眠的内核路径里使用该类型标志需要特别警惕,因为这会引起死锁或者其它系统异常。GFP_HIGHUSER_ MOVABLE优先使用高端内存并且分配的内存具有可移动属性。因此应该选择GFP_HIGHUSER_MOVABLE,因为此宏分配的内存是可迁移的,而GFP_KERNEL,分配的是不可迁移的内存类型。
阅读打卡第四站.docx (17.14 KB, 下载次数: 1)
 
 
 

回复

110

帖子

0

TA的资源

一粒金砂(中级)

8
 

1. 在理想情况下,alloc_pages()函数在伙伴系统能分配的最大内存块约为4MB大小;
2. gfp_mask的低4位来表示。对应ZONE_DMA中分配内存,ZONE_DMA32中分配内存。优先从ZONE_HIGHMEM分配。
3. 使用zonelist,所有可用zone的链表
4. 使用GFP_HIGHUSER_MOVABLE,其为用户空间进程分配内存。具体讲,优先使用高端内存,并且分配的内存具有可移动属性。

 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表