博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
1.3.2 设置中断描述符表和全局描述符表
阅读量:3676 次
发布时间:2019-05-21

本文共 2069 字,大约阅读时间需要 6 分钟。

1.3.2 设置中断描述符表和全局描述符表

setup程序继续为保护模式做准备,此时要通过setup程序自身提供的数据信息对中断描述符表寄存器IDTR和全局描述符表寄存器GDTR进行初始化设置。

小贴士

GDT(Global Descriptor Table,全局描述符表):它是系统中唯一存放段寄存器内容(段描述符)的数组,配合程序进行保护模式下的段寻址。它在操作系统的进程切换中具有重要意义,可理解为所有进程的总目录表,其中存放着每一个任务(task)局部描述符表(LDT,Local Descriptor Table)地址和任务状态段(TSS,Task Structure Segment)地址,用于完成进程中各段的寻址、现场保护与现场恢复。

GDTR(Global Descriptor Table Register,GDT基地址寄存器):GDT可以存放在内存的任何位置,当程序通过段寄存器引用一个段描述符时,需要取得GDT的入口, GDTR所标识的即为此入口。在操作系统对GDT的初始化完成后,可以用LGDT(Load GDT)指令将GDT基地址加载至GDTR。

IDT(Interrupt Descriptor Table,中断描述符表):保存保护模式下所有中断服务程序的入口地址,类似于实模式下的中断向量表。

IDTR(Interrupt Descriptor Table Register,IDT基地址寄存器):IDT基地址寄存器,保存IDT的起始地址。

内核实现代码如下:

//代码路径:boot/setup.s   
 
lidt    idt_48  
lgdt    gdt_48  
 
gdt:  
    .word   0,0,0,0     ! dummy  
 
    .word   0x07FF      ! 8Mb-limit=2047 (2048*4096=8Mb)  
    .word   0x0000      ! base address=0 
    .word   0x9A00      ! code read/exec  
    .word   0x00C0      ! granularity=4096, 386  
 
    .word   0x07FF      ! 8Mb-limit=2047 (2048*4096=8Mb)  
    .word   0x0000      ! base address=0 
    .word   0x9200      ! data read/write  
    .word   0x00C0      ! granularity=4096, 386  
 
idt_48:  
    .word   0       ! idt limit=0 
    .word   0,0     ! idt base=0L 
 
gdt_48:  
    .word   0x800       ! gdt limit=2048, 256 GDT entries  
    .word   512+gdt,0x9 ! gdt base = 0X9xxxx 

这些代码设置所需要的数据分别在idt_48和gdt_48所对应的标号处,它们与寄存器的对应方式如图1-18所示。

 
图1-18 设置GDTR和IDTR

点评

32位的中断机制和16位的中断机制在原理上有比较大的差别,最明显的是16位的中断机制用的是中断向量表,中断向量表的起始位置在0x00000处,这个位置是固定的。32位的中断机制用的是中断描述符表IDT,位置是不固定的,可以由操作系统的设计者根据设计要求灵活安排,由IDTR寄存器来锁定其位置。

GDT表是保护模式下管理段描述符的数据结构,对操作系统自身的运行和管理,以及进程调度有重大意义,后面的章节会有详细讲解。

因为,此时此刻内核尚未真正运行起来,还没有进程,所以现在创建的GDT表的第一项为空,第二项为内核代码段描述符,第三项为内核数据段描述符,其余项皆为空。

IDT表虽然已经设置,实为一张空表,原因是目前已关中断,无须调用中断服务程序。此处反映的是数据“够用即得”的思想。

创建这两个表的过程可理解为是分两步进行的:

(1)在设计内核代码时,已经将两个表写好,并且把需要的数据也写好。

(2)将专用寄存器(IDTR和GDTR)指向表。

此处的数据区域是在内核源代码中设定和编译并直接加载至内存形成的一块数据区域。专用寄存器的指向由程序中的lidt指令和lgdt指令完成,具体操作见图1-18。

值得一提的是,在内存中做出数据的方法有两种:

(1)划分一块内存区域并初始化数据,“看住”这块内存区域,使之能被找到;

(2)由代码做出数据,如用push代码压栈,“做出”数据,此处采用的是第一种方法。

转载地址:http://rkxbn.baihongyu.com/

你可能感兴趣的文章
Java正则表达式工具类
查看>>
SpringSecurity配置过滤Swagger(Boostrap-ui)文档路径
查看>>
SpringBoot实现阿里云手机短信验证码
查看>>
Java8线程安全日期类
查看>>
ThreadLocal实现原理
查看>>
String、StringBuilder、StringBuffer、StringJoiner源码分析
查看>>
Java数据结构与算法——原地哈希算法
查看>>
解决Github访问速度慢以及图片加载慢的问题
查看>>
Java数据结构与算法——有限状态机(DFA)
查看>>
BindException、ConstraintViolationException、MethodArgumentNotValidException入参验证异常分析和全局异常处理解决方法
查看>>
SpringBoot实现微信支付流程+RabbitMQ消息推送
查看>>
文件在线预览开源组件kkFileView
查看>>
Lua脚本语言基础语法
查看>>
MyBatis-Plus 实体entity自动生成器
查看>>
SpringMVC——异步交互技术AJAX
查看>>
SpingMVC——文件的上传下载
查看>>
SpringMVC——拦截器
查看>>
SSM框架终极篇——Spring、SpringMVC、MyBatis整合练习(超级详细)
查看>>
SpringBoot——SpringBoot、SpringClould、微服务
查看>>
理解RESTful架构(转载)
查看>>