在kern/pmap.c 里面会又以下这段代码,要知道boot_alloc只会分配线性地址,真正建立虚拟页和物理页映射关系的在后面的page_alloc.

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

        // create initial page directory.

        kern_pgdir = (pde_t *) boot_alloc(PGSIZE);

        memset(kern_pgdir, 0, PGSIZE);

这里有个疑问,memset仅会接受虚拟地址,而这里boot_alloc分配出的kern_pgdir 是线性地址,这里还“没有建立起实际的物理映射”,怎么就能用memset去把kern_pgdir指向的地址出PGSIZE大小空间的数据所有填充为0.

前面说的话已经又双引號了,嘿嘿。说明这就是个假象,或者说我理解的不够透彻. 这里要感谢Eric eshyong。以及和我一起讨论问题的Essential
On C & Linux的道友.

上面代码部分还处于已经开启分页可是还没有建立起全部的分页映射. 为什么这样说,是由于之前JOS的kernel
作者手动静态的完毕了部分内存的映射,而这部分内存就是物理内存的前4M(0x400000)

在kern/entrypgdir.c 里面

注意这里把虚拟地址的 [0,4M) [KERNBASE,KERNBASE + 4M) 两个区间都映射到同一物理地址区间[0,4M)

所谓的静态映射就是手动的...把一个个地址页面都分配好。例如以下....

Revisit the page table setup in  kern/entry.S  and  kern/entrypgdir.c . Immediately after we turn on paging, EIP is still a low number (a little over 1MB). At what point do we transition to running at an EIP above
KERNBASE? What

makes it possible for us to continue executing at a low EIP between when we enable paging and when we begin running at an EIP above KERNBASE? Why is this transition necessary?

这里就相当于要回答这个问题,在刚刚开启分页的时候(entry.S 里面 cr0 的)

	# Turn on paging.
movl %cr0, %eax
orl $(CR0_PE|CR0_PG|CR0_WP), %eax
movl %eax, %cr0

紧接着此时EIP指令寄存器还指向地址的低空间(1M多一点点的地方)

   不难看出jmp这行代码使得地址空间起了变化,分页机制開始作用

既然分页已经开启了,那么就应当把高地址的KERNBASE映射到物理地址上,之前事实上就已经做好了,这里把虚拟地址的 [0,4M) [KERNBASE,KERNBASE + 4M) 两个区间都映射到同一物理地址区间[0,4M)的目的就在于不要让指令的寻址受到地址空间变化的影响.

(这段代码我重复给出,比較重要)

回到我们原来的问题

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

        // create initial page directory.

        kern_pgdir = (pde_t *) boot_alloc(PGSIZE);

        memset(kern_pgdir, 0, PGSIZE);

这里有个疑问。memset仅会接受虚拟地址,而这里boot_alloc分配出的kern_pgdir 是线性地址,这里还“没有建立起实际的物理映射”,怎么就能用memset去把kern_pgdir指向的地址出PGSIZE大小空间的数据所有填充为0.

在这一步的时候。boot_alloc确实是申请出的线性地址,可是注意!这部分地址早就被静态映射好了。

此时的kern_pgdir 得到的是线性地址,然而它并不须要page_alloc来给它动态的分配实际的内存,由于之前已经分配好了.

memset接受的參数也是线性的(虚拟的)。

二零一四年 十月 摄于妙音寺前

关于JOS 未对全部内存分页映射之前 物理地址映射问题的思考的更多相关文章

  1. 操作系统之Linux的内存分页管理

    内存是计算机的主存储器.内存为进程开辟出进程空间,让进程在其中保存数据.我将从内存的物理特性出发,深入到内存管理的细节,特别是了解虚拟内存和内存分页的概念. 内存 简单地说,内存就是一个数据货架.内存 ...

  2. JVM优化之调整大内存分页(LargePage)

    转自:http://cjjwzs.iteye.com/blog/1059381 本文将从内存分页的原理,如何调整分页大小两节内容,向你阐述LargePage对JVM的性能有何提升作用,并在文末点明了大 ...

  3. Linux的内存分页管理

    作者:Vamei 出处:http://www.cnblogs.com/vamei 严禁转载 内存是计算机的主存储器.内存为进程开辟出进程空间,让进程在其中保存数据.我将从内存的物理特性出发,深入到内存 ...

  4. (理论篇)从基础文件IO说起虚拟内存,内存文件映射,零拷贝

    为了快速构建项目,使用高性能框架是我的职责,但若不去深究底层的细节会让我失去对技术的热爱. 探究的过程是痛苦并激动的,痛苦在于完全理解甚至要十天半月甚至没有机会去应用,激动在于技术的相同性,新的框架不 ...

  5. linux 内存分页

    内存是计算机的主存储器.内存为进程开辟出进程空间,让进程在其中保存数据.我将从内存的物理特性出发,深入到内存管理的细节,特别是了解虚拟内存和内存分页的概念. 内存 简单地说,内存就是一个数据货架.内存 ...

  6. Linux的内存分页管理【转】

    内存是计算机的主存储器.内存为进程开辟出进程空间,让进程在其中保存数据.我将从内存的物理特性出发,深入到内存管理的细节,特别是了解虚拟内存和内存分页的概念. 内存 简单地说,内存就是一个数据货架.内存 ...

  7. 【操作系统之十】内存分页管理与swap

    一.虚拟内存电脑里内存分内存条(这里我们叫物理内存)和硬盘,内存条保存程序运行时数据,硬盘持久保存数据.那么虚拟内存是什么? 程序运行会启动一个进程,进程里有程序段.全局数据.栈和堆,这些都会加载到内 ...

  8. [转帖]运维必读:Linux 的内存分页管理

    运维必读:Linux 的内存分页管理 https://cloud.tencent.com/developer/article/1356431 内存是计算机的主存储器.内存为进程开辟出进程空间,让进程在 ...

  9. C#实现的内存分页机制的一个实例

    C#实现的内存分页机制的一个实例 //多页索引表管理类(全局主索引表管理类) public class MuliPageIndexFeatureClass : IDisposable { protec ...

随机推荐

  1. PCB 线路板人生

    由此开端,增加PCB人生分类栏,后续在此分享PCB 非工作方面所思所想,由于文笔不好,请指正.

  2. 大数据攻城狮之Hadoop伪分布式篇

    对于初学大数据的萌新来说,初次接触Hadoop伪分布式搭建的同学可能是一脸萌笔的,那么这一次小编就手把手的教大家在centos7下搭建Hadoop伪分布式. 底层环境: VMware Workstat ...

  3. [转]RDLC报表格式化format表达式

    本文转自:http://www.cnblogs.com/samlin/archive/2012/04/17/FormatDateTime.html 刚开始接触RDLC报表,觉得RDLC报表提供的格式化 ...

  4. python 11:range(起始索引,终止索引,步数)(默认情况下步数为1,生成从起始索引,每次增加(终止索引-起始索引)/步数,到终止索引前的数字串)

    squares = [] for value in range(1,11): #第三参数默认为1,生成从1开始,每次增加1步数,到11前的10为止的数字串 square = value ** 2 sq ...

  5. [转]ORACLE EXECUTE IMMEDIATE 小结

    转自:http://www.cnblogs.com/huanghai223/archive/2011/06/29/2093660.html   EXECUTE IMMEDIATE 代替了以前Oracl ...

  6. MySQL定期执行任务相关问题

    在sqlyog某数据库下的事件里新建事件,并写入一下代码: DELIMITER $$ ALTER DEFINER=`root`@`%` EVENT `0` ON SCHEDULE EVERY 24 H ...

  7. C# 怎么把类文件如(XXX.cs)转为dll文件

    打开VS2012或2017 ,新建项目,选择  类库(.NET Framework),创建好一个项目 在建好的项目中添加需要转的类文件 然后将项目重新生成后,在项目的Debug下就可以找到对应的dll ...

  8. 最简单的多线程死锁案例代码(Java语言)

    package com.thread.test; public class DeadLock { private static Object firstMonitor = new Object(); ...

  9. js视频学习笔记1

    1:数组赋值的个数长度定义无效,第4个存储的数还是能原封不动打印出来. js的数组是内部有一个变量名叫0,它的值是1,有一变量名叫1,它的值是2.是这样表示的 2:js是弱类型语言,没有var标识符, ...

  10. 【SQL】约束

    1. 添加约束 1)使用ALTER TABLE语句 •添加或删除约束,不会修改其结构 •启用和禁用约束 •通过使用MODIFY子句添加NOTNULL约束 ALTER TABLE <table_n ...