0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

RT-Smart页初始化相关功能及物理页分配算法伙伴系统的实现

RTThread物联网操作系统 来源:RTThread物联网操作系统 作者:我夏了夏天 2022-10-19 10:05 次阅读

想要对 RT-Smart 的物理页内存管理功能有所了解,需要熟悉相关代码:

RT-Smart 页初始化相关功能

物理页分配算法伙伴系统的实现

物理页管理初始化

在系统初始化早期,会先执行 rt_page_init 函数来对物理页管理所需要的数据结构进行初始化,下面是对这段代码的详细解释:

 1#defineARCH_PAGE_SHIFT12
 2#defineARCH_PAGE_SIZE(1<< ARCH_PAGE_SHIFT)
 3#define ARCH_PAGE_MASK      (ARCH_PAGE_SIZE - 1) /* b 1111 1111 1111  */
 4/* 从这 PAGE_START PAGE_END 可以看出,分配给物理页的地址是从 KERNEL_VADDR_START 开始的第 16M 到 128M 之间  */
 5#define HEAP_END        (void*)(KERNEL_VADDR_START + 16 * 1024 * 1024)
 6#define PAGE_START      HEAP_END
 7#define PAGE_END        (void*)(KERNEL_VADDR_START + 128 * 1024 * 1024)
 8static struct page *page_list[ARCH_PAGE_LIST_SIZE];
 9/* 传入给页初始化函数的结构体,存储了物理页管理的地址范围 */
10rt_region_t init_page_region = {
11    (uint32_t)PAGE_START,
12    (uint32_t)PAGE_END,
13};
14/* 物理页管理数据结构 */
15struct page
16{
17    struct page *next;  /* same level next */
18    struct page *pre;   /* same level pre  */
19    uint32_t size_bits; /* if is ARCH_ADDRESS_WIDTH_BITS, means not free */
20    int ref_cnt;        /* page group ref count */
21};
22static struct page* page_start;
23static void*  page_addr;
24static size_t page_nr;
25/* 实际执行物理页管理数据结构的初始化,默认物理页大小为 4K */
26void rt_page_init(rt_region_t reg)
27{
28    int i;
29    LOG_D("split 0x%08x 0x%08x
", reg.start, reg.end);
30    /* 调整物理内存的起始地址为 4K 对齐 */
31    reg.start += ARCH_PAGE_MASK;
32    reg.start &= ~ARCH_PAGE_MASK;
33    reg.end &= ~ARCH_PAGE_MASK;
34    /* 计算管理物理页所需数据结构所占用的内存空间,以及可以有多少可以被分配的物理页 */
35    {
36        /* 计算一个物理页也就是 4k 可以存放多少个 page 结构体 */
37        int nr = ARCH_PAGE_SIZE / sizeof(struct page); 
38        /* 计算总共有多少个可用物理页 */
39        int total = (reg.end - reg.start) >>ARCH_PAGE_SHIFT;
40/*计算需要多少个页的内存用于存放管理页数据结构*/
41intmnr=(total+nr)/(nr+1);
42LOG_D("nr=0x%08x
",nr);
43LOG_D("total=0x%08x
",total);
44LOG_D("mnr=0x%08x
",mnr);
45page_start=(structpage*)reg.start;
46/*计算除去用于管理的内存页,可用于物理页分配的起始地址*/
47reg.start+=(mnr<< ARCH_PAGE_SHIFT);  
48        page_addr = (void*)reg.start;
49        /* 计算有多少个物理页可供分配 */ 
50        page_nr = (reg.end - reg.start) >>ARCH_PAGE_SHIFT;
51}
52LOG_D("align0x%08x0x%08x
",reg.start,reg.end);
53/*初始化空闲page分配链表*/
54for(i=0;i< ARCH_PAGE_LIST_SIZE; i++)
55    {
56        page_list[i] = 0;
57    }
58    /* 初始化可供分配的物理页管理结构体 */
59    for (i = 0; i < page_nr; i++)
60    {
61        page_start[i].size_bits = ARCH_ADDRESS_WIDTH_BITS;
62        page_start[i].ref_cnt = 1;
63    }
64    /* 将所有可供分配的空闲页,使用伙伴算法加入到空闲链表 */
65    while (reg.start != reg.end)
66    {
67        struct page *p;
68        int align_bits;
69        int size_bits;
70        /* 计算合适的物理页大小 size_bits 值 */
71        size_bits = ARCH_ADDRESS_WIDTH_BITS - 1 - rt_clz(reg.end - reg.start);
72        align_bits = rt_ctz(reg.start);
73        if (align_bits < size_bits)
74        {
75            size_bits = align_bits;
76        }
77        /* 从实际物理页地址找到相应的管理页地址 */
78        p = addr_to_page((void*)reg.start);
79        p->size_bits=ARCH_ADDRESS_WIDTH_BITS;
80p->ref_cnt=1;
81/*将相应的管理页结构体加入到页空闲链表上,
82由此可以知道物理页空闲链表上挂接的是物理页的管理结构体*/
83_pages_free(p,size_bits-ARCH_PAGE_SHIFT);
84reg.start+=(1UL<< size_bits);
85    }
86}

物理页管理算法简介

伙伴系统在现代操作系统中被广泛地用于分配连续的物理内存页。其基本思想是将物理内存划分成连续的块,以块作为基本单位进行分配。不同块的大小可以不同,但每个块都由一个或多个连续的物理页组成,物理页的数量必须是 2 的 n 次幂( 0 <= n < 预设的最大值),其中预设的最大值将决定能够分配的连续物理内存区域的最大大小,一般由开发者根据实际需要指定。

当一个请求需要分配 m 个物理页时,伙伴系统将寻找一个大小合适的块,该块包含 $2^n$ 个物理页,且满足 $2^{n-1} < m < 2^n$。在处理分配请求的过程中,大的块可以分裂成两半,即两个小一号的块,这两个块互为伙伴。分裂得到块可以继续分裂,直到得到一个大小合适的块去服务相应的分配请求。在一个块被释放后,分配器会找到其伙伴块,若伙伴块页处于空闲的状态,则将这两个伙伴块进行合并没形成一个大一号的空闲块,然后继续尝试向上合并。由分裂操作和合并操作都是级联的,因此能够很好地缓解外部碎片的问题。

下图表达了伙伴系统的基本思想,基于伙伴块进行分裂与合并。

22866cc4-4ee3-11ed-a3b6-dac502259ad0.png

伙伴系统实现

在 RT-Smart 系统中,使用空闲链表数组来实现伙伴系统。具体来说,全局有一个有序数组,数组的每一项指向一条空闲链表,每条链表将其对应大小的空闲块连接起来,一条链表中的空闲块大小相同。当接收到分配请求后,伙伴分配器首先算出应该分配多大的空闲块,然后查找对应的空闲链表。

想要了解物理页算法的实现过程,那就要熟悉物理页的申请和释放算法,也就是页面释放函数 _pages_free 和物理页申请函数 _pages_alloc。

物理页释放

 1staticint_pages_free(structpage*p,uint32_tsize_bits)
 2{
 3/*根据size_bits获取当前物理页的大小*/
 4uint32_tlevel=size_bits;
 5uint32_thigh=ARCH_ADDRESS_WIDTH_BITS-size_bits-1;
 6structpage*buddy;
 7RT_ASSERT(p->ref_cnt>0);
 8RT_ASSERT(p->size_bits==ARCH_ADDRESS_WIDTH_BITS);
 9/*将该物理页的引用计数减一,如果引用计数不为0则直接返回*/
10p->ref_cnt--;
11if(p->ref_cnt!=0)
12{
13return0;
14}
15/*判断当前页大小是否比最大空闲页小,如果大小为最大空闲页,则直接将该页插入到最大空闲页链表*/
16while(level< high)
17    {
18        /* 根据当前物理页的信息和级别,判断它的 buddy 是否存在 */
19        buddy = buddy_get(p, level);
20        /* 如果当前物理页的 buddy 存在且级别与当前物理页相同,则将他们合并成为更高一级别的物理页 */
21        if (buddy && buddy->size_bits==level)
22{
23page_remove(buddy,level);
24p=(p< buddy) ? p : buddy;
25            level++;
26        }
27        else
28        {
29            /* buddy 不存在,则退出查找 */
30            break;
31        }
32    }
33    /* 将指定级别的空闲页插入到空闲链表中 */
34    page_insert(p, level);
35    return 1;
36}

物理页申请

22be5f4e-4ee3-11ed-a3b6-dac502259ad0.png22dc2a1a-4ee3-11ed-a3b6-dac502259ad0.png

通过上面的物理页释放与分配过程,就实现了 RT-Smart 系统中的物理页管理过程。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 内存管理
    +关注

    关注

    0

    文章

    163

    浏览量

    14057
  • 管理算法
    +关注

    关注

    0

    文章

    3

    浏览量

    5658

原文标题:RT-Smart 物理页内存管理详解

文章出处:【微信号:RTThread,微信公众号:RTThread物联网操作系统】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Linux内存系统: Linux 内存分配算法

    · 减少伙伴算法分配小块连续内存时所产生的内部碎片· 将频繁使用的对象缓存起来,减少分配初始化和释放对象的时间开销· 通过着色技术调整对
    发表于 08-24 07:44

    鸿蒙内核源码分析(内存分配篇):内存的分配方式有哪些

    ,因数组里只有一条数据,所以只有一个段3.初始化了回收双链表和置换算法,采用了LRU置换算法。4.对每一框进行了初始化,每个
    发表于 11-20 10:07

    RT-Smart的资料合集

    可知,RT-Smart 32 位内核运行在地址空间的高地址,而用户程序代码运行在低地址。2、RT-Smart物理内存管理详解伙伴
    发表于 03-22 15:06

    基于RT-Thread操作系统衍生rt-smart实时操作系统简介

    1、rt-smart 实时操作系统简介RT-Thread Smart(简称 rt-smart)嵌入式实时操作
    发表于 06-22 17:56

    基于Windows环境快速体验rt-smart相关资料介绍

    环境(scons)、图形系统配置(menuconfig)及软件包管理功能等工具通过 ART-Pi-Smart SDK 仓库 (Gitee)下载最新的 ART-Pi
    发表于 06-30 12:01

    RT-Smart在riscv64上的系统初始化和异常处理的代码注释

    RT-Smart riscv64汇编注释以rt-smart在全志D1上的代码为例,主要注释了rt-smart在riscv64上的系统初始化
    发表于 02-10 16:43

    Rt-Smart在riscv中的初始化流程

    相关定义bsp\\qemu-virt64-riscv\\driver\\board.h得到ddr的空间规划如下rt-smart针对virt board的初始化整体初始化
    发表于 02-16 14:09

    rt-smart应用程序系统调用实现过程是怎么样的?

    rt-smart应用程序系统调用实现过程是怎么样的? 比如open时候怎么一步一步切换到内核态的?
    发表于 09-08 17:00

    树莓派上rt-smart的应用编程入门

    我们从现在开始会逐步连载RT-Thread Smart(简称rt-smart,甚至有时会称为smart os)的介绍文章,旨在让大家认识,接触到sm
    的头像 发表于 05-13 14:10 2712次阅读
    树莓派上<b class='flag-5'>rt-smart</b>的应用编程入门

    rt-smart移植分析:从树莓派3b入手

    移植rt-smart到最新的板子上具体需要注意哪些细节,哪些才是移植rt-smart的关键点?本文从树莓派3b上移植rt-smart的角度,从头分析rt-sm...
    发表于 01-25 18:48 0次下载
    <b class='flag-5'>rt-smart</b>移植分析:从树莓派3b入手

    优雅的在D1S上运行RT-Smart

    前言 最近在学习 RT-Smart ,正巧有在全志开发者论坛看到这么一篇帖子【惊】在麻雀上运行国产rt-smart系统,看到很多人都在关注 D1S 在 Smart 上的运行情况。如今该
    的头像 发表于 11-16 20:15 1914次阅读

    丝滑的在RT-Smart用户态运行LVGL

    /rt-thread.git 更详细环境配置请移步到— RT-Thread-优雅の在D1S上运行RT-Smart 「Rb君」,公众号:RTThread物联网操作系统优雅的在D1S上运行
    的头像 发表于 11-22 20:20 939次阅读

    RT-Smart riscv64汇编注释

    rt-smart在全志D1上的代码为例,主要注释了rt-smart在riscv64上的系统初始化和异常处理的代码仓库地址https://gitee.com/rtthread/
    的头像 发表于 02-08 21:40 808次阅读

    riscv在rt-smart中的板级初始化

    本文章的代码来自于rt-smart中针对qemu-virt-riscv的bsp 仓库地址 https://gitee.com/rtthread/rt-thread/tree/rt-smart
    的头像 发表于 02-09 17:45 675次阅读

    RT-Smart riscv64汇编注释

    rt-smart在全志D1上的代码为例,主要注释了rt-smart在riscv64上的系统初始化和异常处理的代码
    的头像 发表于 10-12 17:26 342次阅读
    <b class='flag-5'>RT-Smart</b> riscv64汇编注释