OS创建页目录和页
;开始创建页目录项(PDE)
.create_pde: ; 创建Page Directory Entry
mov eax, PAGE_DIR_TABLE_POS ; PAGE_DIR_TABLE_POS = 0x100000
add eax, 0x1000 ; 此时eax为第一个页表的位置及属性
mov ebx, eax ; 此处为ebx赋值,是为.create_pte做准备,ebx为基址。
; 下面将页目录项0和0xc00都存为第一个页表的地址,
; 一个页表可表示4MB内存,这样0xc03fffff以下的地址和0x003fffff以下的地址都指向相同的页表,
; 这是为将地址映射为内核地址做准备
or eax, PG_US_U | PG_RW_W | PG_P ; 页目录项的属性RW和P位为1,US为1,表示用户属性,所有特权级别都可以访问.
; 第1个目录项,在页目录表中的第0个目录项写入第一个页表的位置(0x101000)及属性(7)
mov [PAGE_DIR_TABLE_POS + 0x0], eax
; 一个页表项占用4字节,0xc00表示第768个页表占用的目录项,0xc00以上的目录项用于内核空间,
;页目录第768项指向第一个页表
mov [PAGE_DIR_TABLE_POS + 0xc00], eax
; 也就是页表的0xc0000000~0xffffffff共计1G属于内核,0x0~0xbfffffff共计3G属于用户进程.
sub eax, 0x1000
; 使最后一个目录项指向页目录表自己的地址
mov [PAGE_DIR_TABLE_POS + 4092], eax
;下面创建页表项(PTE)
;把1M低端内存存储在第一页目录所指向的页表0~页表255内,每页4K
mov ecx, 256 ; 1M低端内存 / 每页大小4k = 256
mov esi, 0
mov edx, PG_US_U | PG_RW_W | PG_P ; 属性为7,US=1,RW=1,P=1
.create_pte: ; 创建Page Table Entry
mov [ebx+esi*4],edx ; 此时的ebx已经在上面通过eax赋值为0x101000,也就是第一个页表的地址
add edx,4096
inc esi
loop .create_pte
;创建内核其它页表的PDE
mov eax, PAGE_DIR_TABLE_POS
add eax, 0x2000 ; 此时eax为第二个页表的位置
or eax, PG_US_U | PG_RW_W | PG_P ; 页目录项的属性US,RW和P位都为1
mov ebx, PAGE_DIR_TABLE_POS
mov ecx, 254 ; 范围为第769~1022的所有目录项数量
mov esi, 769
.create_kernel_pde:
mov [ebx+esi*4], eax
inc esi
add eax, 0x1000
loop .create_kernel_pde
ret
指定了物理地址1M的页表 ,具体示意图如下:
关于页目录表:
1、 每个进程有一个属于自己的页目录表,可通过 CR3 寄存器找到
2、 而内核也有一个独立于其它进程的页目录表[上面代码模拟了内核的页目录表],保存在 swapper_pg_dir[] 数组中
3、 当进程切换的时候,只需要将新进程的页目录把地址加载到 CR3 寄存器中即可
4、 创建一个新进程的时候,需要为它分配一个 page,作为页目录表,并将 swapper_pg_dir[] 的高 256 项拷贝过来[上面代码模拟了内核的页目录表769-1023项],低 768 项则清0
//===============================扩展===============================================
上图反映了如下信息:
1、 进程的4G 线性空间被划分成三个部分:进程空间(0-3G)、内核直接映射空间(3G– high_memory)、内核动态映射空间(VMALLOC_START - VMALLOC_END)
2、 三个空间使用同一张页目录表,通过 CR3 可找到此页目录表。但不同的空间在页目录表中页对应不同的项,因此互相不冲突
3、 内核初始化以后,根据实际物理内存的大小,计算出 high_memory、VMALLOC_START、VMALLOC_END 的值。并为“内核直接映射”空间建立好映射关系,所有的物理内存都可以通过此空间进行访问。
4、 “进程空间”和“内核动态映射空间”的映射关系是动态建立的(通过缺页异常)
假设在有三个线性地址 addr1, addr2, addr3 ,分别属于三个线性空间不同部分(0-3G、3G-high_memory、vmalloc_start-vmalloc_end),但是最终都映射到物理页面1:
1、 三个地址对应不同的页表和页表项
2、 但是页表项的高20bit肯定是1,表示物理页面的索引号是1
3、 同时,根据高20bit,可以从 mem_map[]中找到对应的struct page结构,struct page 用于管理实际的物理页面(就是实际物理页面的物理地址了,到这里就不绕弯子了,顺便想到高速缓冲的匹配命中操作是用哈希表,换算出的要访问的实际物理地址拿到哈希表的输入计算一下哈希值,看看有没命中)(红线)
4、 从线性地址最终的,根据页目录表,页表,可以找到物理地址
5、 struct page和物理地址之间很容易互相转换
6、 从物理地址,可以很容易的反推出在内核直接映射空间的线性地址(蓝线)。要想得到在进程空间或者内核动态映射空间的对应的线性地址,则需要遍历相应的“虚存区间”链表。
关于页目录表:
1、 每个进程有一个属于自己的页目录表,可通过 CR3 寄存器找到
2、 而内核也有一个独立于其它进程的页目录表,保存在 swapper_pg_dir[] 数组中
3、 当进程切换的时候,只需要将新进程的页目录把地址加载到 CR3 寄存器中即可
4、 创建一个新进程的时候,需要为它分配一个 page,作为页目录表,并将swapper_pg_dir[] 的高256项拷贝过来,低768项则清0
linux0.11版本,所有进程共享同一个页目录而各自使用不同的页表,该共享的页目录就放在物理地址最前面的4k
//===============================END===============================================
地址转换图:
程序运行时虚拟地址转化为物理地址过程:
OS创建页目录和页的更多相关文章
- Linux从头学15:【页目录和页表】-理论 + 实例 + 图文的最完全、最接地气详解
作 者:道哥,10+年嵌入式开发老兵,专注于:C/C++.嵌入式.Linux. 关注下方公众号,回复[书籍],获取 Linux.嵌入式领域经典书籍:回复[PDF],获取所有原创文章( PDF 格式). ...
- php创建简单的列表页
php创建简单的列表页 样例 代码 <?php $userInfo[] = array( 'id'=>'1', 'username'=>'fry', 'sex'=>'nan', ...
- 【Mysql】InnoDB 引擎中的页目录
一.页目录和槽 接上一篇,现在知道记录在页中按照主键大小顺序串成了单链表. 那么我使用主键查询的时候,最顺其自然的办法肯定是从第一条记录,也就是 Infrimum 记录开始,一直向后找,只要存在总会找 ...
- 内核知识第八讲,PDE,PTE,页目录表,页表的内存管理
内核知识第八讲,PDE,PTE,页目录表,页表的内存管理 一丶查看GDT表. 我们通过WinDbg + 虚拟机可以进行双机调试.调试一下看下GDT表 我们知道,GDT表中.存储的是存储段信息. 保存了 ...
- 如何创建Filter的属性页
本篇文档我们将要讲述如何给一个filter创建一个属性页,通过CBasePropertyPage基类.这篇文档的实例代码演 示了创建属性页的步骤,这里我们假设我们要创建属性页的视频filter支持饱和 ...
- Word 2007 如何设置正文第一页----目录显示正文从第一页开始
最近学校里开始要求写论文了,其中有个目录中的页码都不是从第一页开始的,毕竟前面还有封面.中英文摘要.目录等,所以正文内容就不是从第一页开始的了,但是很多的书上所有正文都是从第一页开始的,我的论文如何才 ...
- 内核module读取进程页目录
根据当前CR3寄存器内容,读取对应物理内存中的页目录页,并进行解析 1: void dumpPageDirectoryEntry(u32 entry) 2: { 3: u8 present; 4: u ...
- 用C#操作IIS创建虚拟目录和网站
#region CreateWebsite 添加网站 public string CreateWebSite(string serverID, string serverComment, string ...
- 配置ASM以及创建恢复目录
本次配置ASM沿用了搭建RAC的环境配置,系统选用CENTOS6.8 首先本地配置YUM,安装GRID集群件所需要的RPM包 [root@rac01 Packages]# cd /etc/yum.re ...
随机推荐
- springboot注册到consul中报错:Spring MVC found on classpath, which is incompatible with Spring Cloud
今天在做springboot整合成springCloud并注册到consul中时,发现若注册到consule中成功 则不能启动swagger,且不能提供任何API服务,要是能提供API服务则不能注册到 ...
- LINUX CGROUP总结
简介: Linux CGroup全称Linux Control Group, 是Linux内核的一个功能,用来限制,控制与分离一个进程组群的资源(如CPU.内存.磁盘输入输出等).这个项目最早是由Go ...
- 从入门到精通,Java学习路线导航
引言最近也有很多人来向我"请教",他们大都是一些刚入门的新手,还不了解这个行业,也不知道从何学起,开始的时候非常迷茫,实在是每天回复很多人也很麻烦,所以在这里统一作个回复吧. Ja ...
- 自己用ansible加shell 写的自动安装kubernetes的脚本
脚本地址:https://github.com/shatianxiaozi/auto_install_k8s.git 1. 下载 git clone https://github.com/shatia ...
- pymysql操作mysql数据库
1.建库 import pymysql # 建库 try: conn=pymysql.connect( host='127.0.0.1', port=3306, user='root', passwd ...
- Linux安全:Linux如何防止木马
(一)解答战略 去企业面试时是有多位竞争者的,因此要注意答题的维度和高度,一定要直接秒杀竞争者,搞定高薪offer. (二)解答战术 因为Linux下的木马常常是恶意者通过Web的上传目录的方式来上传 ...
- Linux之mysql的安装与,主从设置
一,MYSQL(mariadb) MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可. 开发这个分支的原因之一是:甲骨文公司收购了MySQL后,有将MySQL ...
- CentOS7.X基于LAMP环境搭建cacti
1.搭建好LAMP环境 2.登录数据库创建cacti create database cacti default character set utf8; 创建cacti的账户密码 grant all ...
- Windows Server 2008搭建单域环境
前言 一个典型的单域环境由主机,DC(Domain Controller域控制器).DNS服务器组成.DNS.DC都可以有多个,以实现负载均衡和容错 域中的计算机通过DNS解析域控制器,然后向域控制器 ...
- Vue中的button事件
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...