Linux内核开发基础0--实模式,保护模式,长模式

实模式

又称为地址模式,它的实体现在两个方面:

  1. 运行真实的指令,对指令的动作不做区分
  2. 发往内存的地址是真实的,对任何地址都不加限制的发往内存

实模式下的寄存器

都是16位的
按照用途分类:
在这里插入图片描述

实模式下如何取指令以及访问数据

指令与数据不加区分的放在内存中,都是二进制数据
CS :IP指向的地方被解释为指令
DS/ES/SS :AX/BX/CX/DX/EX/DI/SI/BP/SP指向的地方被解释为数据
(其中:SS和SP决定栈段)
段寄存器左移四位 + 通用寄存器中的值/常数 —>形成地址 由这个地址去访问内存 (内存管理模型)
在这里插入图片描述
在这里插入图片描述

实模式下的中断

中断是CPU响应外部事件的一种方式

中断向量表

存放中断响应(服务)代码所在地址
每一个条目都由代码段地址和段内偏移组成的
在这里插入图片描述

中断号

中断号是服务函数在中断向量表上的偏移地址

IDTR寄存器

CPU中的一个特定的寄存器,保存了中断表地址中断表长度(中断表的范围信息)

中断如何实现实现

先保存CS和IP,然后装载需要跳转到的位置上的CS和IP

第一种情况:硬中断:中断控制器给CPU发送一个电平信号,CPU做出应答,中断控制器接收到应答后将中断号告诉CPU,CPU根据中断号做跳转
第二种情况:软中断:CPU执行INT指令,根据INT指令后跟随的常数,做跳转。这个常数就是中断号

中断号(偏移量) + IDTR中的中断表地址 ----> 响应代码段的其中一个条目
将这个条目的基地址和偏移地址装入CS:IP
在这里插入图片描述

保护模式

应对更高的计算量,更大的内存容量的需求

实模式下寄存器都是16位的,寻址只能指到2的16次方=65535 也就是最大容量为64KB处
保护模式下就将寄存器都设为32位的

解决了内存访问大小的问题,之前的实模式的两个特征 却变为了累赘:

  1. CPU对指令不加区分的执行
  2. 对访问内存的地址不加限制

保护模式下这两问题也都会被解决

保护模式的特点

  1. 增加了一些控制寄存器和段寄存器
  2. 扩展通用寄存器的位宽,所有通用寄存器都是32位
  3. 可以单独使用低16位,也可以将低16位分为两个8位寄存器使用
    在这里插入图片描述

保护模式对两个问题的解决

解决第一个问题:指令不加区分地执行:
通过实现CPU特权级来区分哪些指令和哪些资源可以被访问
解决第二个问题:内存访问不受保护:
通过实现段描述符,对内存进行保护转化为对段进行保护

特权级

特权级分为4级,分别对应着保护模式的四个控制寄存器CR0,CR1,CR2,CR3
每个特权级可以执行的指令数量不同
R0可以执行所有命令 从R0到R3递减
在这里插入图片描述

段描述符

保护模式下的段寄存器是16位的,而内存信息是32位的,无法放下,所以要找地方借
实际段描述符占用64位空间:
在这里插入图片描述
多个段描述符在内存中可形成全局段描述符,该表的基地址和长度由CPU和GDTR寄存器指示
在这里插入图片描述
以前我们的段寄存器作为基地址 配合上IP或者xS等段寄存器的偏移地址就可以直接访问内存
现在段寄存器作为 具体段描述符的索引(类似数组索引)
配合上GDTR里面的信息:包括段全局描述符表的基地址(类似数组0号元素的基地址)
和 段全局描述符表长度(类似数组长度 防止数组访问越界)
有这些信息可以找到具体的段描述符,再 根据里面的段信息判断能否合法访问

保护模式下 更强大的段寄存器 — 段选择子

在这里插入图片描述
影子寄存器依靠硬件来工作,程序员不可见
影子寄存器是为了减少性能损耗而设计
每次访问内存都要去内存中查表,性能损失太大
影子寄存器是一个段描述符的高速缓存,64位,存放8字节的段描述符的数据

段描述符索引就是上面所说的用于定位段描述符的索引

TI指定是从GDT还是LDT中寻找,一般都是0

RPL指示了访问者的权限级别 常常是RPL = CPL

CPL是当前权限级别(Current Privilege Level)
当前正在执行的代码所在的段的特权级,存在于cs寄存器的低两位 CPL标识了代码能够达到的最高的特权级别

DPL是描述符权限级别(Descriptor Privilege Level)
存储在段描述符中,规定访问该段的权限级别,每个段的DPL固定
进程在访问一个段时,需要进行特权级检查,一般要求 DPL > max{CPL,RPL} , 级别至少要相同才能通过检查

保护模式平坦模型

分段模型有很多缺陷 现代操作系统都会使用分页模型
x86 CPU 并不能直接使用分页模型, 而是要在分段模型的前提下, 根据需要决定是否要开启分页。 因为这是硬件的规定, 程序员是无法改变的。
可以简化设计, 来使分段成为一种“虚设”, 这就是保护模式的平坦模型

32位寄存器最多能产生4GB大小的地址
一个段的长度只能是4GB
可以将所有段的基地址设为0
段的长度设为0XFFFFF
段长度的粒度为4KB
所有段都指向同一个(0~4GB-1)字节大小的地址空间

GDT_START:
knull_dsc: dq 0
;第一个段描述符CPU硬件规定必须为0
kcode_dsc: dq 0x00cf9e000000ffff
;段基地址=0, 段长度=0xfffff
;G=1,D/B=1,L=0,AVL=0
;P=1,DPL=0,S=1		//DPL为0  最高权限CPL=0时才能访问
;T=1,C=1,R=1,A=0
kdata_dsc: dq 0x00cf92000000ffff
;段基地址=0, 段长度=0xfffff
;G=1,D/B=1,L=0,AVL=0
;P=1,DPL=0,S=1
;T=0,C=0,R=1,A=0
GDT_END:

GDT_PTR:
GDTLEN dw GDT_END-GDT_START-1
GDTBASE dd GDT_START

保护模式下的中断

实模式下中断:CPU直接通过中断向量表中的值来装载CS:IP寄存器
保护模式下的中断:不能直接查表跳转,需要进行权限检查,特权级切换
这样一来中断向量表里面就应该包含更多的信息:进化为中断门了—>
在这里插入图片描述
中断门和陷阱门唯一的不同也就是置0的不同,陷阱门不会将IF位置0。

与上面通过段描述符寻址的机制类似:
同样的, 保护模式要实现中断, 也必须在内存中有一个中断向量表, 同样是由 IDTR 寄存器指
向, 只不过中断向量表中的条目变成了中断门描述符
在这里插入图片描述
这种情况下的查表需要有几个预先的检查:
CPU 首先会检查中断号是否大于最后一个中断门描述符,x86 CPU 最大支持256 个中断源( 即中断号: 0~255)
检查描述符类型( 是否是中断门或者陷阱门)
检查是否为系统描述符
检查是不是存在于内存中。

检查中断门描述符中的段选择子指向的段描述符

最后做权限检查:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值