独辟蹊径品内核
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.2 系统门

前面说到描述符表项除了有段描述符之外,还有系统段描述符,当段描述符中的S位为0的时候表示这个一个系统段描述符。系统段描述符号包括中断门、陷阱门、任务门、以及调用门。中断门和陷阱门用来描述一个中断例程,他们的入口地址依次存放在中断描述符表中。48位的IDTR寄存器的高32位指向这个表,低16位表示该表的界限,lidtr指令用来加载一个48位的操作数到IDTR寄存器。中断门和陷阱门如图1.9所示。其中16位的选择子和32位的Offset偏移地址指定了一个中断处理例程的地址。Type指示了门的类型,其组合见表1.2。陷阱门和中断门的格式类似,外部中断的处理例程的描述符项被称为中断门,而异常处理例程的描述符则被称为陷阱门。严格来说,中断是由外部设备向CPU发出的,CPU经过地址译码,取指令,指令译码,指令执行等流水步骤,在最后会检查CPU中断请求线是否有信号,所以中断是一个异步事件,CPU在执行指令期间,外部设备随时可以发出中断请求。而异常是一个同步事件,比如除0错误,是CPU自己在指令期触发的。另外还可以通过执行CPU指令int x触发软件异常。当发生中断/异常的时候,CPU利用中断/异常号到中断向量表中索引得到门描述符,然后调用描述符指定的处理例程。

调用门和中断门类似,只是其中Reserve字段被用来表示Param Count,表示调用门的参数的个数(以4字节为单位)。调用门可以用来实现低级别的权限向高级别权限切换,也可以用来实现系统调用。前面说过,不同权限级别使用不同的堆栈,而系统调用的时候,如果需要传递参数的话,就需要把当前低级别要传递的参数拷贝到高级别的堆栈中取,而Param Count指定了拷贝参数的数量。当执行CALL Seg:Offset或者JMP Seg:Offset等转移指令的时候,如果段选择子Seg选中的是一个调用门,CPU会转向调用门指定的入口地址+Offset的地方执行,Offset一般为0。调用门在实际中没有被使用。Linux中的系统调用是通过int 0x80来实现系统调用的,这是一个陷阱门。

任务门是用来实现任务切换的,注意在图1.8中描述的任务段描述符是段描述的一种,可以通过它来实现任务切换,而这里的任务门是门描述符的一种,不要把两者搞混淆了。任务门的格式如图1.10所示。其中16位TSS Selector是TSS段选择子,当CALL,JMP或者IRET等转移指令执行的时候,如果转移目标Seg:Offset指向的是一个任务门,CPU将从任务门中取出16位的选择子,然后利用这个选择子的高13位作为全局描述符表的索引,找到对应的任务段描述符,然后从中取出任务状态段TSS的地址,最后切换到该TSS指定的任务。任务门在实际中也没有被使用。