科技 > 操作系统 > Linux

【原创】(六)Linux内存管理 - zoned page frame allocator - 1

316人参与2019-10-06

背景

说明:

  1. kernel版本:4.14
  2. arm64处理器,contex-a53,双核
  3. 使用工具:source insight 3.5, visio

1. 介绍

之前的系列内存管理文章基本上描述的是物理页面的初始化过程,以及虚拟页面到物理页面的映射建立过程,从这篇文章开始,真正要涉及到页面的分配了。接下来的文章会围绕着分区页框分配器(zoned page frame allocator)来展开,其中会包含大家熟知的buddy system分析。

本文会先围绕着涉及到的数据结构,以及大体的流程做一个整体的分析,后续会针对这个流程中的细节进行更详细的拆解,我已经迫不及待了。

2. 数据结构

2.1 概述

先回顾一下(五)linux内存管理zone_sizes_init的数据结构图:

上述的结构体,描述的是下面这张图:

node ---> zone ---> page的组织关系,其中buddy system中,页面都是以2的次幂来组织成链表,比如free_area[0],对应的是1个page链表,其中又根据不同的migrate_xxxx类型来组织,如下图:

arm64max_order默认值为11,page_size=4k,因此总共有0 ~ 1011个链表数组,链表中的连续的页面为2^0 ~ 2^10,对应大小为4k ~ 4m

可以通过cat /proc/pagetypeinfo来查看下系统的页面信息,如下图:

可以通过cat /proc/zoneinfo来查看nodezone计数信息:

2.2 migrate类型

从上边的图中可以看到migrate_xxx不同的迁移类型,表明页面的移动属性,并在可能的情况下通过将相同属性的页面分组在一起来抑制内存的连续碎片。

enum migratetype {
    migrate_unmovable,
    migrate_movable,
    migrate_reclaimable,
    migrate_pcptypes,   /* the number of types on the pcp lists */
    migrate_highatomic = migrate_pcptypes,
#ifdef config_cma
    /*
     * migrate_cma migration type is designed to mimic the way
     * zone_movable works.  only movable pages can be allocated
     * from migrate_cma pageblocks and page allocator never
     * implicitly change migration type of migrate_cma pageblock.
     *
     * the way to use it is to change migratetype of a range of
     * pageblocks to migrate_cma which can be done by
     * __free_pageblock_cma() function.  what is important though
     * is that a range of pageblocks must be aligned to
     * max_order_nr_pages should biggest page be bigger then
     * a single pageblock.
     */
    migrate_cma,
#endif
#ifdef config_memory_isolation
    migrate_isolate,    /* can't allocate from here */
#endif
    migrate_types
};

2.3 __gfp_xxx请求标志(gfp_mask)

__gfp_xxx为内部使用的标志,在include/linux/gfp.h文件中,外部不应该使用这些flag,这些标志在页面申请的时候使用,其中gfp表示get free page

罗列部分如下:

2.4 alloc_xxxx分配标志(alloc_flags)

分配标志定义在mm/internal.h文件中,在页面的分配函数中与gfp_mask分开使用,这些标志时用于内部函数的分配。

2.5 struct alloc_context

在页面分配的过程中,有一个结构叫struct alloc_context,这个结构用于存储各个函数之间传递的参数。这种思想在平时的coding中是可以去借鉴的,比如有些人写代码很喜欢用全局变量,改成这种context的形式,在各个函数之间传递显得更为优雅。直接看代码吧:

/*
 * structure for holding the mostly immutable allocation parameters passed
 * between functions involved in allocations, including the alloc_pages*
 * family of functions.
 *
 * nodemask, migratetype and high_zoneidx are initialized only once in
 * __alloc_pages_nodemask() and then never change.
 *
 * zonelist, preferred_zone and classzone_idx are set first in
 * __alloc_pages_nodemask() for the fast path, and might be later changed
 * in __alloc_pages_slowpath(). all other functions pass the whole strucure
 * by a const pointer.
 */
struct alloc_context {
    struct zonelist *zonelist;
    nodemask_t *nodemask;
    struct zoneref *preferred_zoneref;
    int migratetype;
    enum zone_type high_zoneidx;
    bool spread_dirty_pages;
};

3. build_all_zonelists

在上篇文章中描述到各个zone,实际上各个zone最终组织起来是在build_all_zonelists函数中实现的:

整体完成的工作也比较简单,将所有node中可用的zone全部添加到各个node中的zonelist中,也就是对应的struct pglist_data结构体中的struct zonelist node_zonelists字段。

这一步之后,准备工作基本就绪,进行页面申请的工作就可以开始了。

4. alloc_pages

下面的流程开始真正的页面申请了,在内部的实现中通过__alloc_pages来实现的:

在页面分配时,有两种路径可以选择,如果在快速路径中分配成功了,则直接返回分配的页面;快速路径分配失败则选择慢速路径来进行分配。

4.1 fast path

快速路径分配,是通过get_page_from_freelist来完成的,具体的流程及分析如下图所示:

4.2 slow path

慢速路径分配,最终也会调用get_page_from_freelist,流程分析如下:

您对本文有任何疑问!!点此进行留言回复

推荐阅读

猜你喜欢

Linux常用网络工具之批量主机服务扫描工具nmap使用介绍

07-23

必会!Linux系统 为命令配置别名

07-10

编译安装基于nginx与lua的高性能web平台-openresty

04-10

vmstat/top/iostat/route/sar 常用命令

08-27

ELK重难点总结和整体优化配置

03-22

VMware安装以及新建CentOS~图文超详细叙述

05-30

Linux(CentOS)--软件包管理rpm,yum以及Linux中的人任务计划

03-11

Linux date cal bc和一些快捷键学习

05-13

热门评论