美文网首页
[OS64][021]源码阅读:程序4-8 申请分配连续64个可

[OS64][021]源码阅读:程序4-8 申请分配连续64个可

作者: AkuRinbu | 来源:发表于2019-06-05 11:44 被阅读0次

学习笔记

使用教材(配书源码以及使用方法)
《一个64位操作系统的设计与实现》
http://www.ituring.com.cn/book/2450
https://www.jianshu.com/p/28f9713a9171

源码结构

/***************************************************
*       版权声明
*
*   本操作系统名为:MINE
*   该操作系统未经授权不得以盈利或非盈利为目的进行开发,
*   只允许个人学习以及公开交流使用
*
*   代码最终所有权及解释权归田宇所有;
*
*   本模块作者:  田宇
*   EMail:      345538255@qq.com
*
*
***************************************************/
  • 配书代码包 :第4章 \ 程序 \ 程序4-8

程序4-8 运行结果

  • 实现内存管理函数init_memory、物理页分配函数alloc_pages、以及页结构管理函数page_init
    程序4-8 申请分配连续64个物理页.png

源码阅读 memory.c

下面的代码,以注释的形式加入了大量自己的理解,作为学习过程的记录,不可避免地存在一定的混乱和前后矛盾(如果有需要建议还是直接阅读配书的官方代码)

如何对位图置位?

[C语言]模拟内存物理页,申请连续64个物理页,对应位图置1
https://www.jianshu.com/p/313b2d5a366a

程序4-8 数据结构与内存示意图

[OS64][022]源码阅读:程序4-8 数据结构与内存示意图
https://www.jianshu.com/p/b1debc1b1a54

main.c : 申请分配连续64个可用物理页

void Start_Kernel(void)
{
. . .
    struct Page * page = NULL;  
. . . 
   page = alloc_pages(ZONE_NORMAL,64,PG_PTable_Maped | PG_Active | PG_Kernel);
. . .
}

memory.c

/***************************************************
*       版权声明
*
*   本操作系统名为:MINE
*   该操作系统未经授权不得以盈利或非盈利为目的进行开发,
*   只允许个人学习以及公开交流使用
*
*   代码最终所有权及解释权归田宇所有;
*
*   本模块作者:  田宇
*   EMail:      345538255@qq.com
*
*
***************************************************/

#include "memory.h"
#include "lib.h"


unsigned long page_init(struct Page * page,unsigned long flags)
{
    if(!page->attribute)
    {
        /*
            对于一个崭新的页面而言,page_init函数是对页结构进行初始化
        */
        *(memory_management_struct.bits_map + ((page->PHY_address >> PAGE_2M_SHIFT) >> 6)) |= 1UL << (page->PHY_address >> PAGE_2M_SHIFT) % 64;
        page->attribute = flags;
        page->reference_count++;
        page->zone_struct->page_using_count++;
        page->zone_struct->page_free_count--;
        page->zone_struct->total_pages_link++;
    }
    else if((page->attribute & PG_Referenced) || (page->attribute & PG_K_Share_To_U) || (flags & PG_Referenced) || (flags & PG_K_Share_To_U))
    {
        /*
            如果当前页面结构属性或参数flags中含有引用属性(PG_Referenced)或共享属性(PG_K_Share_To_U),
            那么就只增加struct page结构体的引用计数和struct zone结构体的页面被引用计数
        */
        page->attribute |= flags;
        page->reference_count++;
        page->zone_struct->total_pages_link++;
    }
    else
    {
        /*
            否则就仅仅是添加页表属性,并置位bit映射位图的相应位。
        */
        *(memory_management_struct.bits_map + ((page->PHY_address >> PAGE_2M_SHIFT) >> 6)) |= 1UL << (page->PHY_address >> PAGE_2M_SHIFT) % 64; 
        page->attribute |= flags;
    }
    return 0;
}


unsigned long page_clean(struct Page * page)
{
    if(!page->attribute)
    {
        page->attribute = 0;
    }
    else if((page->attribute & PG_Referenced) || (page->attribute & PG_K_Share_To_U))
    {       
        page->reference_count--;
        page->zone_struct->total_pages_link--;
        if(!page->reference_count)
        {
            page->attribute = 0;
            page->zone_struct->page_using_count--;
            page->zone_struct->page_free_count++;
        }
    }
    else
    {
        *(memory_management_struct.bits_map + ((page->PHY_address >> PAGE_2M_SHIFT) >> 6)) &= ~(1UL << (page->PHY_address >> PAGE_2M_SHIFT) % 64);

        page->attribute = 0;
        page->reference_count = 0;
        page->zone_struct->page_using_count--;
        page->zone_struct->page_free_count++;
        page->zone_struct->total_pages_link--;
    }
    return 0;
}


void init_memory()
{
    int i,j;
    unsigned long TotalMem = 0 ;
    struct E820 *p = NULL;  
    
    color_printk(BLUE,BLACK,"Display Physics Address MAP,Type(1:RAM,2:ROM or Reserved,3:ACPI Reclaim Memory,4:ACPI NVS Memory,Others:Undefine)\n");
    p = (struct E820 *)0xffff800000007e00;


    /*
        代码清单4-61 获得物理内存信息
    */ 
    for(i = 0;i < 32;i++)
    {
        color_printk(ORANGE,BLACK,"Address:%#018lx\tLength:%#018lx\tType:%#010x\n",p->address,p->length,p->type);
        unsigned long tmp = 0;
        if(p->type == 1)
            TotalMem +=  p->length;

        memory_management_struct.e820[i].address += p->address;

        memory_management_struct.e820[i].length  += p->length;

        memory_management_struct.e820[i].type    = p->type;
        
        memory_management_struct.e820_length = i;

        p++;
        if(p->type > 4 || p->length == 0 || p->type < 1)
            break;      
    }
    
    // 此刻的TotalMem是 9f000h+7fef0000h=7ff8f000h

    color_printk(ORANGE,BLACK,"OS Can Used Total RAM:%#018lx\n",TotalMem);


    /*
    
        代码清单 4-62 计算可用物理页数
        
        Address:0x000000 Length:0x00009f00 Type=0x0001
            start:0x0  end:0x0
        Address:0x100000 Length:0x7fef0000 Type=0x0001
            start:0x200000  end:0x7fe00000
            
        当end<=start时,说明该物理内存段大小<=2MB,即无法分配一个2MB的物理页
        
        计算得知,总的内存可以分配的物理页数是1022(十进制)页,这其中包括了内核程序已经占用的内存
    */


    TotalMem = 0;

    for(i = 0;i <= memory_management_struct.e820_length;i++)
    {
        unsigned long start,end;
        if(memory_management_struct.e820[i].type != 1)
            continue;
        start = PAGE_2M_ALIGN(memory_management_struct.e820[i].address);
        end   = ((memory_management_struct.e820[i].address + memory_management_struct.e820[i].length) >> PAGE_2M_SHIFT) << PAGE_2M_SHIFT;
        if(end <= start)
            continue;
        TotalMem += (end - start) >> PAGE_2M_SHIFT;
    }
    
    // 此刻的TotalMem是 对齐后可使用的2MB物理页页数
    color_printk(ORANGE,BLACK,"OS Can Used Total 2M PAGEs:%#010x=%010d\n",TotalMem,TotalMem);


    /*
    
        代码清单 4-68 初始化位图 bits_map
        
    
    */



    // 此刻的TotalMem是 0x fffc 0000 + 0x4 0000 = 0x 1 0000 0000
    // 
    TotalMem = memory_management_struct.e820[memory_management_struct.e820_length].address 
                + memory_management_struct.e820[memory_management_struct.e820_length].length;
    
    //color_printk(WHITE,RED,"List4-68 TotalMem:%#018lx\n",TotalMem);

    
    // bits map construction init
    
    // end_brk : 0x114a08  bits_map:0x115000
    // 从内核程序结束地址 end_brk 起的4KB上边界对齐处 存入一个 bits_map 
    memory_management_struct.bits_map = (unsigned long *)((memory_management_struct.end_brk + PAGE_4K_SIZE-1) & PAGE_4K_MASK);
    
    // bits_size = 0x800 按2MB对齐后物理地址空间可分页数 (800H = 2048D) 
    // 从 Address:0x00开始的全部:可以用物理段、内存空洞以及ROM空间
    // bits_length=0x100 位图长度 (100H = 256D)
    memory_management_struct.bits_size = TotalMem >> PAGE_2M_SHIFT;

    // 8位等于1字节,1位表示一个页
    // bits_length是位图长度,
    memory_management_struct.bits_length = (((unsigned long)(TotalMem >> PAGE_2M_SHIFT) + sizeof(long) * 8 - 1) / 8) & ( ~ (sizeof(long) - 1));

    // 将整个bits_map 全部置1,以标注非内存页(内存空洞和ROM空间)已被使用
    memset(memory_management_struct.bits_map,0xff,memory_management_struct.bits_length);        //init bits map memory

    
    
    
    /*
    
        代码清单 4-69 初始化结构体 struct page
    
    */
    

    // pages construction init
    
    // 在bits_map 之后,找一个4K对齐的地址处开始放 pages_struct
    // bits_map_end:0x115800     pages_struct: 0x116000
    memory_management_struct.pages_struct = (struct Page *)(((unsigned long)memory_management_struct.bits_map 
                                                        + memory_management_struct.bits_length + PAGE_4K_SIZE - 1) & PAGE_4K_MASK);
    
    memory_management_struct.pages_size = TotalMem >> PAGE_2M_SHIFT;
    
    memory_management_struct.pages_length = ((TotalMem >> PAGE_2M_SHIFT) * sizeof(struct Page) + sizeof(long) - 1) & ( ~ (sizeof(long) - 1));
    
    // 将整个 pages_struct 清零 
    memset(memory_management_struct.pages_struct,0x00,memory_management_struct.pages_length);   //init pages memory

    
    
    
    /*
    
        代码清单 4-70 为 struct zone 结构体建立存储空间并对其进行初始化
    
    */

    //zones construction init
    // 在 struct page之后 4K边界对齐的地址处放 struct zone
    // pages_struct_end:0x12a000     zones_struct: 0x12a000
    memory_management_struct.zones_struct = (struct Zone *)(((unsigned long)memory_management_struct.pages_struct 
                                                            + memory_management_struct.pages_length + PAGE_4K_SIZE - 1) & PAGE_4K_MASK);
    // 是说有多少个Zone
    memory_management_struct.zones_size   = 0;
    
    // 是说结构体 struct Zone 数组的长度 暂且算作5个
    memory_management_struct.zones_length = (5 * sizeof(struct Zone) + sizeof(long) - 1) & (~(sizeof(long) - 1));



    /*
    
        代码清单 4-71 
    
    */  

    for(i = 0;i <= memory_management_struct.e820_length;i++)
    {
        
        unsigned long start,end;
        struct Zone * z;
        struct Page * p;
        unsigned long * b;


        // 找到一个可用的物理内存段
        // 现在只有一个物理内存段可用( TYPE=0x01 且 大小 >2MB )  
        //      Address:0x100000 Length:0x7fef0000 Type=0x0001
        //          start:0x200000  end:0x7fe00000

        if(memory_management_struct.e820[i].type != 1)
            continue;
        start = PAGE_2M_ALIGN(memory_management_struct.e820[i].address);
        end   = ((memory_management_struct.e820[i].address + memory_management_struct.e820[i].length) >> PAGE_2M_SHIFT) << PAGE_2M_SHIFT;
        if(end <= start)
            continue;
        
        //zone init
        // 一开始这个zones_size是0 同时表示这是第一个可用的zone
        //color_printk(WHITE,RED,"List4-71  memory_management_struct.zones_size:%#018lx\n",memory_management_struct.zones_size);
        z = memory_management_struct.zones_struct + memory_management_struct.zones_size;
        memory_management_struct.zones_size++;



        // start:0x200000
        z->zone_start_address = start;
        z->zone_end_address = end;
        z->zone_length = end - start;

        z->page_using_count = 0;
        z->page_free_count = (end - start) >> PAGE_2M_SHIFT;

        z->total_pages_link = 0;

        z->attribute = 0;
        z->GMD_struct = &memory_management_struct;

        // 本区域包含的struct Page 结构体数量 
        // 一个可以用的物理页由一个 struct page 结构体管理
        // 这里已经是只需要 type=0x01以及>2MB的 可用物理段 了
        // 本质上是从物理地址 0x200000 开始的内存
        // (也就是说除掉内核程序占用的一部分内存,还有1022个2MB空闲可用物理页)
        // 这里z->pages_length的数值就是 0x3fe=1022
        z->pages_length = (end - start) >> PAGE_2M_SHIFT;
        
        // bits_map_end:0x115800     pages_struct: 0x116000
        // z->pages_group 是struct Page 结构体数组指针
        // pages_struct++的话 起始是加 40字节 40D=28H 是一个struct Page 结构占用的字节数
        z->pages_group =  (struct Page *)(memory_management_struct.pages_struct + (start >> PAGE_2M_SHIFT));


        // 由于这里 (start >> PAGE_2M_SHIFT) 计算得到1
        // 同时 struct page 结构体大小是 40字节 40D=28H
        // 所以在输出截图中 z->pages_group 显示是 0x116028
        //color_printk(WHITE,RED,"List4-71  start:%#018lx \t start >> PAGE_2M_SHIFT:%#018lx\n",start, start >> PAGE_2M_SHIFT);
        //color_printk(WHITE,RED,"List4-71  z->pages_length:%#018lx\n",z->pages_length);
        //color_printk(WHITE,RED,"List4-71  z->pages_group:%#018lx\n",z->pages_group);


        //page init
        //为区域内的每个物理页 对应的 页结构体 填上真实的物理地址等信息
        p = z->pages_group;
    
        for(j = 0;j < z->pages_length; j++ , p++)
        {
            // 每个物理页 属于 哪个 区域
            p->zone_struct = z;
            // start:0x200000 这是从物理地址0x200000开始分配可用2MB物理页
            p->PHY_address = start + PAGE_2M_SIZE * j;
            p->attribute = 0;

            p->reference_count = 0;

            p->age = 0;

            // 该物理页对应位图位置 请零 表示该可用物理页空闲
            *(memory_management_struct.bits_map + ((p->PHY_address >> PAGE_2M_SHIFT) >> 6)) ^= 1UL << (p->PHY_address >> PAGE_2M_SHIFT) % 64;

        }
        
        
    }
    
    /*
    
        代码清单 4-72  
        物理地址的第一个2MB是 0x00 到0x1FFFFF 这里有BootLoader残留的机器码以及Kernel 对应Pages的第一个Page[0]
    
    */
    
    
    

    /////////////init address 0 to page struct 0; because the memory_management_struct.e820[0].type != 1
    
    memory_management_struct.pages_struct->zone_struct = memory_management_struct.zones_struct;

    memory_management_struct.pages_struct->PHY_address = 0UL;
    memory_management_struct.pages_struct->attribute = 0;
    memory_management_struct.pages_struct->reference_count = 0;
    memory_management_struct.pages_struct->age = 0;

    /////////////

    // 代码清单 4-70 的时候 假设有5个结果体 现在经过一系列配置 可以计算出真正结构体的数量 
    // 因为现在只有一个 zone 可用 所以其实 这里的 zones_size是1, 这里的 zones_length就是 0x50  50H=80D
    memory_management_struct.zones_length = (memory_management_struct.zones_size * sizeof(struct Zone) + sizeof(long) - 1) & ( ~ (sizeof(long) - 1));
    //color_printk(WHITE,RED,"List4-72  zones_length:%#018lx\n", memory_management_struct.zones_length);


    /*
    
        代码清单 4-73 
    
    */


    color_printk(ORANGE,BLACK,"bits_map:%#018lx,bits_size:%#018lx,bits_length:%#018lx\n",memory_management_struct.bits_map,memory_management_struct.bits_size,memory_management_struct.bits_length);

    color_printk(ORANGE,BLACK,"pages_struct:%#018lx,pages_size:%#018lx,pages_length:%#018lx\n",memory_management_struct.pages_struct,memory_management_struct.pages_size,memory_management_struct.pages_length);

    color_printk(ORANGE,BLACK,"zones_struct:%#018lx,zones_size:%#018lx,zones_length:%#018lx\n",memory_management_struct.zones_struct,memory_management_struct.zones_size,memory_management_struct.zones_length);

    ZONE_DMA_INDEX = 0; //need rewrite in the future
    ZONE_NORMAL_INDEX = 0;  //need rewrite in the future



    /*
    
        代码清单 4-74
    
    */
    

    for(i = 0;i < memory_management_struct.zones_size;i++)  //need rewrite in the future
    {
        struct Zone * z = memory_management_struct.zones_struct + i;
        
        // 打印当前区域的 起始地址、结束地址、指向本区域的struct page结构体数组指针、区域内可用的物理页数量
        color_printk(ORANGE,BLACK,"zone_start_address:%#018lx,zone_end_address:%#018lx,zone_length:%#018lx,pages_group:%#018lx,pages_length:%#018lx\n",z->zone_start_address,z->zone_end_address,z->zone_length,z->pages_group,z->pages_length);

        // 起始地址在0x1 0000 0000 的区域 未曾经过页表映射
        if(z->zone_start_address == 0x100000000)
            ZONE_UNMAPED_INDEX = i;
    }
    
    // end_of_struct 内存页管理结构的结尾地址
    // |--- 内核程序 --- | -----------      内存管理页结构                 ---------- |
    // |--- 内核程序 --- | ---- bits_map ---- | ---- pages ---- | ----- zones ---- |
    // end_of_struct = 0x12a150 预留一段内存空间防止越界访问
    // end_of_struct:0x000000000012a150 0x000000000012a050  
    memory_management_struct.end_of_struct = (unsigned long)((unsigned long)memory_management_struct.zones_struct + memory_management_struct.zones_length + sizeof(long) * 32) & ( ~ (sizeof(long) - 1));   ////need a blank to separate memory_management_struct

    
    
    /*
    
        代码清单4-75 初始化 struct Global_Memory_Descriptor 其中使用的结构体 struct Page
        结合代码清单4-79 理解 page_init
    
    */
    
    // end_of_struct 内存页管理结构的结尾地址
    color_printk(ORANGE,BLACK,"start_code:%#018lx,end_code:%#018lx,end_data:%#018lx,end_brk:%#018lx,end_of_struct:%#018lx\n",memory_management_struct.start_code,memory_management_struct.end_code,memory_management_struct.end_data,memory_management_struct.end_brk, memory_management_struct.end_of_struct);

    
    i = Virt_To_Phy(memory_management_struct.end_of_struct) >> PAGE_2M_SHIFT;


    // 将 系统内核 与 内存管理单元结构所占物理页的page结构体 全部初始化成
    // PG_PTable_Maped(经过页表映射的页) | PG_Kernel_Init(内核初始化程序) | PG_Active(使用中的页) | PG_Kernel(内核层页)属性
    for(j = 0;j <= i;j++)
    {
        page_init(memory_management_struct.pages_struct + j,PG_PTable_Maped | PG_Kernel_Init | PG_Active | PG_Kernel);
    }




    /*
    
        代码清单 4-76 清空页表项
    
    */


    Global_CR3 = Get_gdt();
    
    // PML4 - PDPT - PDT - PT

    color_printk(INDIGO,BLACK,"Global_CR3\t:%#018lx\n",Global_CR3);
    color_printk(INDIGO,BLACK,"*Global_CR3\t:%#018lx\n",*Phy_To_Virt(Global_CR3) & (~0xff));
    color_printk(PURPLE,BLACK,"**Global_CR3\t:%#018lx\n",*Phy_To_Virt(*Phy_To_Virt(Global_CR3) & (~0xff)) & (~0xff));

    // 将PML4页表的前10个页表项清零
    // #define Phy_To_Virt(addr)    ((unsigned long *)((unsigned long)(addr) + PAGE_OFFSET))
    // PML4 单个页表项是8字节 这里强制转换成 unsigned long 类型的指针  +1 就是+8字节
    for(i = 0;i < 10;i++)
        *(Phy_To_Virt(Global_CR3)  + i) = 0UL;
    
    // 强制TLB 自动刷新
    flush_tlb();
}




/*

    number: number < 64

    zone_select: zone select from dma , mapped in  pagetable , unmapped in pagetable

    page_flags: struct Page flages

*/

struct Page * alloc_pages(int zone_select,int number,unsigned long page_flags)
{
    
    /*
    
        代码清单 4-80 
        目前,Bochs虚拟机只能开辟出2 GB的物理内存空间,以至于虚拟平台仅有一个可用物理内存段,
        因此ZONE_DMA_INDEX、ZONE_NORMAL_INDEX和ZONE_UNMAPED_INDEX 三个变量均代表同一内存区域空间,
        即使用默认值0代表的内存区域空间。
    
    */
    
    
    int i;
    unsigned long page = 0;

    int zone_start = 0;
    int zone_end = 0;

    switch(zone_select)
    {
        case ZONE_DMA:
                zone_start = 0;
                zone_end = ZONE_DMA_INDEX;

            break;

        case ZONE_NORMAL:
                zone_start = ZONE_DMA_INDEX;
                zone_end = ZONE_NORMAL_INDEX;

            break;

        case ZONE_UNMAPED:
                zone_start = ZONE_UNMAPED_INDEX;
                zone_end = memory_management_struct.zones_size - 1;

            break;

        default:
            color_printk(RED,BLACK,"alloc_pages error zone_select index\n");
            return NULL;
            break;
    }
    
    
    /*
    
        代码清单 4-81 从该区域空间中遍历出符合申请条件的struct page结构体组
        
    */
    
    for(i = zone_start;i <= zone_end; i++)
    {
        struct Zone * z;
        unsigned long j;
        unsigned long start,end,length;
        unsigned long tmp;

        if((memory_management_struct.zones_struct + i)->page_free_count < number)
            continue;

        z = memory_management_struct.zones_struct + i;
        start = z->zone_start_address >> PAGE_2M_SHIFT;
        end = z->zone_end_address >> PAGE_2M_SHIFT;
        length = z->zone_length >> PAGE_2M_SHIFT;

        
        // 起始页的BIT映射位图只能检索tmp = 64 - start % 64;次,
        // 即起始页只有 tmp 个位置可以检索 对应 tmp个物理页
        // 随后借助代码j += j % 64 ? tmp : 64将索引变量j调整到对齐位置处
        // 这里的64应该是是指 unsigned long 变量的8字节 64位
        // 也就是说 表示 bits_map的第一个 unsigned long 变量表示第0~63的物理页,里面有 tmp个位置可以检索
        // 下一次要走到第二个unsinged long 变量,表示第 64~127 的物理页
        /*
            start = 1   tmp = 64-1%64=63    j+= 1%64?63:64  j=1+63=64
            start = 2   tmp = 64-2%64=62    j+= 2%64?62:64  j=2+62=64
            start = 3   tmp = 64-3%64=61    j+= 3%64?61:64  j=3+61=64
        
        */

        tmp = 64 - start % 64;


        // 程序4-8的 start = 0x01 end=0x1023
        // 表示要从 [start,end]这么多个物理页中找一个区间,这个区间是64个连续的物理页
        // 程序4-8 可以直接从start开始 就能找到 连续64个物理页
        // 事实上,第一个找到的物理页的物理地址就是 0x200000
        // 外层for循环实际只会执行一次
        for(j = start;j <= end;j += j % 64 ? tmp : 64)
        {
            // j >> 6 就是 j / 64 看看当前检索的页对应的bit位在第几个unsigned long 变量里
            unsigned long * p = memory_management_struct.bits_map + (j >> 6);
            // shift 当前检索的页在该 unsigned long 变量中的偏移量
            // Hex:      0   0      0   0       0   0   0   0       0   0   0   0       0   0    0   0  
            // Binary: 0000 0000 0000 0000  0000 0000 0000 0000  0000 0000 0000 0000  0000 0000 0000 0000 
            unsigned long shift = j % 64;
            
            // k是下标,表示从当前的unsigned long变量的二进制第shift位开始检索,包括下一个unsigned long变量在内
            // 能不能够凑出来一个连续的64个物理页的区间
            // 也就是看 当前的unsigned long 变量的第shift位到下一个unsigned long变量的第shift-1位,是不是一直都是0
            // 0表示空闲,表示可以用
            // 如果是就申请这个区间
            // 如果不是k就要++
            unsigned long k;
            for(k = shift;k < 64 - shift;k++)
            {
                // 除非可以保证能申请到连续的64个物理页
                // 否则不会进入循环
                // 就是要一口气申请连续的64个物理页
                if( !(((*p >> k) | (*(p + 1) << (64 - k))) & (number == 64 ? 0xffffffffffffffffUL : ((1UL << number) - 1))) )
                {
                    
                    unsigned long   l;
                    page = j + k - 1;
                    
                    // page 表示相对于 整个 pages_struct的偏移
                    // l 表示 要申请的64个物理页的 偏移
                    for(l = 0;l < number;l++)
                    {
                        struct Page * x = memory_management_struct.pages_struct + page + l;
                        // page_init函数负责对位图置位,设置页结构的属性等等
                        page_init(x,page_flags);
                    }
                    // 上面的for一口气把64个物理页申请好了 因此这里的page仍旧是第一个申请的物理页的偏移
                    goto find_free_pages;
                }
            }
        
        }
    }

    return NULL;

find_free_pages:

    return (struct Page *)(memory_management_struct.pages_struct + page);
}


相关文章

网友评论

      本文标题:[OS64][021]源码阅读:程序4-8 申请分配连续64个可

      本文链接:https://www.haomeiwen.com/subject/sdpjxctx.html