loader将控制权交给内核后,内核首先切换堆栈和gdt
然后进行init的工作 包括
a初始化8259A 和IDT;使cpu能接受中断
b初始化GDT中的TSS和LDT两个描述符,以及TSS;
c初始化进程表struct s_proc {
stack_frame regs;
u16
ldt_sel;
DESCRIPTOR ldts[LDT_SIZE];
u32
pid;
char
p_name[16];
} ;
stack_frame.eip = (u32)TestA; TestA 就是一个我们随意写的普通功能函数 以后可以替换为其他与os功能相关的函数;
然后指定时钟中断处理程序 ;让8259A可以接受时钟中断;
时钟中断是硬件中断 , 8253//54的count0端口
直接硬连 到了 irq0端口 就实现了此中断。
至此就能形成一个可被中断的程序,但这个被编写的程序并不能运行(想一想)。
调用restart()就可以使编写的这个开始运行了。
restart:
mov esp ,[p_proc_ready]
lldt [esp + p_LDT_SEL]
.......
说明:
保护模式下的代码访问(只是一个概念性的简单说明,实际情况还要看具体的资料)
A代码 cpl=3 直接访问 dpl =2 的代码 系统会产生异常,提示错误。
A代码 cpl=3 通过门调用访问 dpl =2 的代码 假如门的dpl也为3 则此次访问被系统允许。
门调用也是一种调用 所以必然会产生压栈出栈操作,并且涉及到不止一个堆栈。一般都是被调用者处理压栈调用者 ss esp cs eip的工作。
在压栈以前 系统检查cpl dpl rpl符合条件 就进入了门调用,就发生了特权的转移。