linux kernel物理内存概述(四)

本文详细介绍了Linux内核中的页面分配函数如alloc_pages和get_free_pages,以及不同内存区域的管理,包括填充0的页面、释放页面和内存分配的修饰符。特别关注了zonelist和zone的数据结构,以及它们在内存分配决策中的作用。
摘要由CSDN通过智能技术生成

目录

分配页面

1、分配物理页面的核心函数

2、分配一个页面

3、分配填充0的页面

4、释放页面

5、分配掩码类型

zonelist


分配页面

1、分配物理页面的核心函数

struct page *alloc_pages(gfp_t gfp_mask ,unsigned int order);
unsigned long __get_free_pages(gfp_t gfp_mask,unsgined int order);

返回是内存的内核虚拟地址,如果所分配内存是线性映射的物理内存,则直接返回线性映射区的内核空间虚拟地址,不会使用高端内存。

2、分配一个页面

#define alloc_page(gfp_mask) alloc_pages(gfp_mask,0)
#define __get_free_page(gfp_mask) __get_free_pages(gfp_mask,0)

3、分配填充0的页面

unsigned long get_zeroed_page(gfp_t gfp_mask)

4、释放页面

void __free_pages(struct page *page,unsigned int order);
#define __free_page(page) ___free_pages((page),0)
#define free_page(addr) free_pages((addr),0)

5、分配掩码类型

  • 内存管理区修饰符 __GFP_DMA __GFP_DMA32 __GFP_HIGHMEM GFP_MOVABLE
  • 移动修饰符 __GFP_RECLAIMABLE,__GFP_HARDWALL
  • 水位修饰符 __GFP_HIGH,__GFP_ATOMIC,GFP_MEMALLOC,GFP_NOMEMALLOC
  • 页面回收修饰符 __GFP_IO,__GFP_FS ...
  • 行为修饰符 __GFP_COLD,__GFP_NOWARN,__GFP_ZERO

组合使用

  • GFP_KERNEL,常用,可能睡眠阻塞
  • GFP_ATOMIC,保证不休眠并且分配成功
  • GFP_NOWAIT,分配过程不允许睡眠
  • GFP_NOFS 不会访问任何的文件系统的接口和操作
  • GFP_USER 用户空间进程用来分配内存
  • GFP_HIGHUSER ,用户空间 优先ZONE_HIGHNEN
  • GFP_HIGHUSER_MOVABLE ,用户空间 优先ZONE_HIGHNEN,页面可迁移
  • GFP_TRANSHUGE 透明页面分配

alloc_pages函数分析 ...

zonelist

每个内存节点在内核中抽象成一个zone,zone划分为多个区域,如ZONE_DMA,ZONE_DMA32,ZONE_NORMAL等。 在内核中使用zonelist数据结构管理一个内存节点zone

struct zonelist {
    struct zoneref _zonerefs[MAX_ZONES_PER_ZONELIST + 1];
};

struct zoneref{
    struct zone* zone;//指向实际的zone
    int zone_idx;//编号,通常0表示最低的zone,如ZONE_DMA32,1表示ZONE_NORMAL
    
}
typedef struct palist_data{
    struct zonelist node_zonelists[MAX_ZONELISTS];
}
  • zonelist时所有可用zone的链表,排在第一个的zone是页面分配器首选的。
  • 内存数据结构pglist_data中有两个zonelist。一个是ZONELIST_FALLBACK,指向本地zone;另外是ZONELIST_NOFALLBACK,用于NUMA系统,指向远端内存节点zone
  • 建立zonelist 使用build_zonelist 如系统中有一个内存节点,有两个zone
  • ZONE_NORMAL:_zonerefs[0]->zone_idx=1
  • ZONE_DMA32:_zonerefs[1]->zone_idx=0 分配物理内存时,优先使用ZONE_NORMAL

first_zoneslist() 以GFP_KERNEL为例,gfp_zone(GFP_KERNEL)返回1,即highest_zoneidx=1,第一个zone是ZONE_NORMAL,其zone_idx=1 for_each_zonelist_nodemask() 会遍历ZONE_NORMAL和ZONE_DMA32

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

为了维护世界和平_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值