学习笔记
使用教材(配书源码以及使用方法)
《一个64位操作系统的设计与实现》
http://www.ituring.com.cn/book/2450
https://www.jianshu.com/p/28f9713a9171
源码结构
- 配书代码包 :第4章 \ 程序 \ 程序4-8
程序4-8 内存示意图
物理地址
0x00 0x100000 0x200000
|-------------------------------|-------------------------------|--------------------
0 1MB 2MB
起始物理地址
---- 0x00 ~ 0x1FFFFF ----
0x7c00 boot.bin
0x7E00 INT 15H获取的物理地址空间信息
0x8000 软盘根目录区或FAT表读入缓冲区
0x10000 Loader.bin
0x100000 kernel.bin
0x100000 + 0x1000 PML4
0x100000 + 0x2000 PDPT
0x100000 + 0x3000 PDE
0x100000 + GDT IDT TSS
0x115000 struct bits map
0x116000 struct pages
0x12a000 struct zones
---- 0x200000 ~~~
程序4-8 数据结构
位图 bits map
位图一位标识是一张物理页的使用状况,
0: 空闲可用 ,1:已使用
整个内存条的大小是
0x1 0000 0000 = 0x fffc 0000+0x 4000
位图要描述整个内存条(可用内存+不可用内存),设置了
2MB大小
的物理页,那么位图需要对应0x800=2048
张物理页,因此,位图的bits_size
等于0x800
,需要0x800
这么多位,自然只需要bits_length=0x800 ÷ 8=0x100
这么多字节来存储整个位图而,可用的物理空间是从
起始物理地址 0x100000 长度0x7FEF0000
,换算成可用的2MB物理页
的个数是0x3fe=1022
张对于位图而言,位图里
第一个字节的第0位
对应于物理地址0x00~0x1FFFFF
即内存条的第一个2MB空间,位图里的第一个字节的第1位
才是对应于0x200000~0x3FFFFF
即内存条的第二个2MB空间(这里才是第一个可申请使用2MB物理页)程序4-8
memory.c
init_memory(){}
这里完成事实上的开辟内存空间给位图
将整个bits_map 全部置1,以标注非内存页(内存空洞和ROM空间)已被使用
memset(memory_management_struct.bits_map,0xff,memory_management_struct.bits_length); //init bits map memory
等价于
memset(0x115000, 0xff, 0x100);
页结构体 pages
struct Page
{
指向本物理页所属的区域结构体
struct Zone * zone_struct;
本物理页的起始物理地址
unsigned long PHY_address;
本物理页的属性
unsigned long attribute;
本物理页的被引用次数
unsigned long reference_count;
本物理页的创建时间
unsigned long age;
};
- 按照2MB大小分割后的每一个物理页由一个
struct page {}
进行管理 - 整个内存条,分割后的2MB大小物理页是
0x800
张 - 单个
struct page{}
大小是0x28 = 40字节 - 因此对应于整个内存条的page结构体一共是
0x800 * 40 = 0x14000
这么多字节 - 程序4-8
memory.c
init_memory(){}
这里完成事实上的开辟内存空间给页结构体们
// 将整个 pages_struct 清零
memset(memory_management_struct.pages_struct,0x00,memory_management_struct.pages_length); //init pages memory
等价于
memset(0x116000,0x00,0x14000); //init pages memory
区域结构体 zones
- 整个内存条拥有以下的区域
i Address Length Type
zones[0] 0x00000000 0x0009f000 0x00001
zones[1] 0x0009f000 0x00001000 0x00002
zones[2] 0x000e8000 0x00018000 0x00002
zones[3] 0x00100000 0x7fef0000 0x00001
zones[4] 0x7fff0000 0x00010000 0x00003
zones[5] 0xfffc0000 0x00040000 0x00002
type = 1
才是可用区域,同时由于现在物理页的大小是2MB,那么zone[0]
不足以分配一张物理页,因此可用物理段只有zones[3] 0x00100000 0x7fef0000 0x00001
单个
struct Zone
大小是0x50 = 80
字节
struct Zone
{
0xffff 8000 0011 6028
struct Page * pages_group;
本区域可用的物理页个数
unsigned long pages_length;
本区域的起始物理地址
(不是struct Zone 结构体存放位置,
而是区域的起始物理地址,
即zones[3]里面的0x100000
按照2MB对齐后的首地址就是0x200000)
unsigned long zone_start_address;
0x7FE00000
unsigned long zone_end_address;
本区域占用的字节数
unsigned long zone_length;
本区域的属性
unsigned long attribute;
指向全局结构体的指针
struct Global_Memory_Descriptor * GMD_struct;
本区域已使用的物理页数
unsigned long page_using_count;
本区域空闲的物理页数
unsigned long page_free_count;
本区域物理页被引用次数
(同一个物理页可以被多个线性地址引用)
unsigned long total_pages_link;
};
全局结构体 Global_Memory_Descriptor
struct E820
{
unsigned long address;
unsigned long length;
unsigned int type;
}__attribute__((packed));
struct Global_Memory_Descriptor
{
struct E820 e820[32];
unsigned long e820_length;
0x115000
unsigned long * bits_map;
unsigned long bits_size;
unsigned long bits_length;
0x116000
struct Page * pages_struct;
unsigned long pages_size;
unsigned long pages_length;
0x12a000
struct Zone * zones_struct;
unsigned long zones_size;
unsigned long zones_length;
unsigned long start_code , end_code , end_data , end_brk;
内存页管理结构的结尾地址
unsigned long end_of_struct;
};
参考资料
- 如何解读E820
[OS64位][020]源码阅读:程序4-7 计算可用的物理内存页数
https://www.jianshu.com/p/8ec3ea9120ce
- 程序 4-8 运行
[OS64][021]源码阅读:程序4-8 申请分配连续64个可用物理页
https://www.jianshu.com/p/f1c159ddc917