reactos操作系统实现(14)

下面来分析一下系统任务是怎么样初始化的,先来看这行代码

/* Setup the TSS descriptors and entries */

Ki386InitializeTss(Tss,Idt,Gdt);

在这Ki386InitializeTss函数里就是进行初始化系统任务的工作,因此要分析这个函数代码,才可以理解系统任务的工作。

#001 VOID

#002 FASTCALL

#003 Ki386InitializeTss(IN PKTSS Tss,

# 004 IN PKIDTENTRY Idt,

# 005 IN PKGDTENTRY Gdt)

#006 {

#007 PKGDTENTRY TssEntry,TaskGateEntry;

#008

#009 /* Initialize the boot TSS. */

#010 TssEntry = &Gdt[KGDT_TSS / sizeof(KGDTENTRY)];

#011 TssEntry->HighWord.Bits.Type = I386_TSS;

#012 TssEntry->HighWord.Bits.Pres = 1;

#013 TssEntry->HighWord.Bits.dpl = 0;

这里初始化系统引导任务。第10代码是根据前面设置的任务选择子来找到入口。

11行到第13代码设置引导任务段的属性

#014 KiInitializeTSS2(Tss,TssEntry);

调用KiInitializeTSS2函数来进行任务段参数设置,并设置I/O位图和中断情况。

#015 KiInitializeTSS(Tss);

调用函数KiInitializeTSS设置I/O位置开始位置,设置中断标志,设置局部描述符和内核堆栈。

#016

#017 /* Load the task register */

#018 Ke386SetTr(KGDT_TSS);

加载内核任务到TR寄存器。

#019

#020 /* Setup the Task Gate for Double Fault Traps */

#021 TaskGateEntry = (PKGDTENTRY)&Idt[8];

#022 TaskGateEntry->HighWord.Bits.Type = I386_TASK_GATE;

#023 TaskGateEntry->HighWord.Bits.Pres = 1;

#024 TaskGateEntry->HighWord.Bits.dpl = 0;

#025 ((PKIDTENTRY)TaskGateEntry)->Selector = KGDT_DF_TSS;

这里设置中断描述符表里的双重故障处理任务。从INTEL的文档里可以看到它的双重故障的中断号是8,所以这里就是设置第8项的中断描述符。双重故障是怎么样产生的呢?这是INTELcpu进入中断处理函数后,紧跟着又发生了一次中断,这样的情况,就叫双重故障。在操作系统里,一般需要把这种情况检查出来,强制地停止这种应用程序的错误,或者恢复系统的资源。比如当调用缺页中断处理后,紧跟着又产生缺页中,这样就会产生双重故障。导致系统无限循环下去,就会死机了。在我新装的电脑里,设置主板与ATI显示卡不对,就导致操作系统无限循环中断下去,然后系统就死机了。

#026

#027 /* Initialize the TSS used for handling double faults. */

#028 Tss = (PKTSS)KiDoubleFaultTSS;

#029 KiInitializeTSS(Tss);

#030 Tss->CR3 = __readcr3();

#031 Tss->Esp0 = PtrToUlong(KiDoubleFaultStack);

#032 Tss->Eip = PtrToUlong(KiTrap8);

这里双重故障的入口地址。

#033 Tss->Cs = KGDT_R0_CODE;

#034 Tss->Fs = KGDT_R0_PCR;

#035 Tss->Ss = Ke386GetSs();

#036 Tss->Es = KGDT_R3_DATA | RPL_MASK;

#037 Tss->Ds = KGDT_R3_DATA | RPL_MASK;

#038

#039 /* Setup the Double Trap TSS entry in the GDT */

#040 TssEntry = &Gdt[KGDT_DF_TSS / sizeof(KGDTENTRY)];

#041 TssEntry->HighWord.Bits.Type = I386_TSS;

#042 TssEntry->HighWord.Bits.Pres = 1;

#043 TssEntry->HighWord.Bits.dpl = 0;

#044 TssEntry->BaseLow = (USHORT)((ULONG_PTR)Tss & 0xFFFF);

#045 TssEntry->HighWord.Bytes.BaseMid = (UCHAR)((ULONG_PTR)Tss >> 16);

#046 TssEntry->HighWord.Bytes.BaseHi = (UCHAR)((ULONG_PTR)Tss >> 24);

#047 TssEntry->LimitLow = KTSS_IO_MAPS;

上面设置双重故障的任务,并设置了GDT里的描述符。

#048

#049 /* Now setup the NMI Task Gate */

#050 TaskGateEntry = (PKGDTENTRY)&Idt[2];

#051 TaskGateEntry->HighWord.Bits.Type = I386_TASK_GATE;

#052 TaskGateEntry->HighWord.Bits.Pres = 1;

#053 TaskGateEntry->HighWord.Bits.dpl = 0;

#054 ((PKIDTENTRY)TaskGateEntry)->Selector = KGDT_NMI_TSS;

#055

#056 /* Initialize the actual TSS */

#057 Tss = (PKTSS)KiNMITSS;

#058 KiInitializeTSS(Tss);

#059 Tss->CR3 = __readcr3();

#060 Tss->Esp0 = PtrToUlong(KiDoubleFaultStack);

#061 Tss->Eip = PtrToUlong(KiTrap2);

#062 Tss->Cs = KGDT_R0_CODE;

#063 Tss->Fs = KGDT_R0_PCR;

#064 Tss->Ss = Ke386GetSs();

#065 Tss->Es = KGDT_R3_DATA | RPL_MASK;

#066 Tss->Ds = KGDT_R3_DATA | RPL_MASK;

#067

#068 /* And its associated TSS Entry */

#069 TssEntry = &Gdt[KGDT_NMI_TSS / sizeof(KGDTENTRY)];

#070 TssEntry->HighWord.Bits.Type = I386_TSS;

#071 TssEntry->HighWord.Bits.Pres = 1;

#072 TssEntry->HighWord.Bits.dpl = 0;

#073 TssEntry->BaseLow = (USHORT)((ULONG_PTR)Tss & 0xFFFF);

#074 TssEntry->HighWord.Bytes.BaseMid = (UCHAR)((ULONG_PTR)Tss >> 16);

#075 TssEntry->HighWord.Bytes.BaseHi = (UCHAR)((ULONG_PTR)Tss >> 24);

#076 TssEntry->LimitLow = KTSS_IO_MAPS;

上面设置不可屏蔽的中断任务。

#077}

相关文章

react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接...
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc ...