小弟多次想把调用门和RPL分开单独说,但几次尝试都没有成功,我发现它们之间是紧偶合、密不可分,RPL的产生主要是为解决系统调用时的“越权”问题,系统调用的实现方式中,以调用门和中断门最为适合。由于以后我们将用中断门实现自己的系统调用,故在此本着扩充知识面的目的给大伙儿介绍调用门,通过调用门的实例,让大伙儿理解特权级那点事儿。
处理器只有通过“门结构”才能由低特权级转移到高特权级,处理器就是这样设计的,我们必须要遵循它的用法,对处理器来说,操作系统只是它的应用而已。
门结构是什么呢?就是记录一段程序起始地址的描述符。
描述符有多种,刚才所说的一致性代码段,虽然它里面全是代码,但它本身是内存段,并不是指具体的一段例程,所以可以用“段描述符”来“描述”。还有一种称为“门描述符”的结构,用来描述一段程序。进入这种神奇的“门”,处理器便能转移到更高的特权级上。
门描述符同段描述符类似,都是8字节大小的数据结构,用来描述门中通向的代码。一共有4种门结构,下面4张图是4种门描述符的结构,咱们先看图,然后咱们再简要介绍
大家看图中的4种门描述符,它们与段描述符最大的不同是,除了任务门外,其它三种门都是对应到一段例程,即对应一段函数,而不是像段描述符对应的是一片内存区域。任何程序都属于某个内存段,所以程序确切的地址必须用“代码段选择子+段内偏移量”来描述,可见,门描述符是基于段描述符,例程是用段描述符来给出基址的,所以门描述符中要给出代码段的选择子,但光给出基址远远不够,还必须给出例程的偏移量,这就是门描述符中记录的是选择子和偏移量的原因。
任务门描述符可以放在GDT、LDT和IDT(中断描述符表,后面章节在介绍中断时大伙儿就清楚了)中,调用门可以位于GDT、LDT中,中断门和陷阱门仅位于IDT中。
任务门、调用门都可以用call和jmp指令直接调用,原因是这两个门描述符都是位于描述符表中,要么是GDT,要么是LDT,访问它们同普通的段描述符是一样的,也必须要通过选择子,因此只要在call或jmp指令后接任务门或调用门的选择子便可调用它们了。陷阱门和中断门只存在于IDT中,因此不能主动调用,只能由中断信号来触发调用。
任务门有点特殊,它是用任务TSS的描述符选择子来描述一个任务,有关TSS的内容会在用户进程部分介绍。除任务门之外,另外的三个门描述符都是用代码段选择子及偏移地址来描述一段程序例程。但是,无论是哪种门描述符,它们中所记录的信息都已经可以确定所描述的对象(例程或任务)了,所以在被调用时,CPU都会忽略调用指令中的偏移量。如:假设某调用门描述符位于GDT中第1个位置,这样的指令“call 0x0008:0x1234”,在调用此调用门时,偏移量0x1234会被CPU忽略。