Leo*_*9 _ 1 x86 operating-system kernel osdev context-switch
我有一个带有时钟中断的简单工作(32 位保护模式)内核。我可以看到这个中断正在工作,因为它多次打印 \xc2\xab\xc2\xa0clock\xc2\xa0\xc2\xbb 。我还可以看到这个中断将控制权交还给内核,因为它在几次时钟中断后在屏幕上打印 \xc2\xab\xc2\xa0Kernel has stop\xc2\xa0\xc2\xbb ,就像它应该的那样。中断与内核位于同一代码段中。
\n我没有设置任何 TSS,但它正在工作。我可以在这篇文章( https://web.archive.org/web/20160326062442/http://jamesmolloy.co.uk/tutorial_html/10.-User%20Mode.html )上读到,当发生中断时,CPU将查看选定的 TSS 段以更新寄存器。
\n如果我没有\xe2\x80\x99t 有这个 TSS ,它如何工作?是因为当中断发生时CPU仍然会自动推送EIP、CS、EFLAGS、EPS、SS并在iret上恢复它们吗?
\n如果我加载单个 TSS,该中断如何知道它应该使用该 TSS?使用ltr指令将在GDT内获取相应的tss段?
\n并不是真正相关,但是当使用硬件上下文切换并跳转到一个 TSS 时,它会在返回时自动跳转到上一个(没有下一个字段,所以 I\xe2\x80\x99m 有点丢失)tss 段吗?
\n这些问题我无法从我的学校课程、osdev 或这个论坛中真正得到明确的答案。
\n正如Michael Petch在评论中解释的那样,如果中断处理程序以相同的权限执行,则不需要 TSS。
\nSS:SP仅当中断将在当前代码环的更高特权环中执行时(例如从环 3 到环 0 的转换),CPU 才会从 TSS 读取必要的对。
\n第三版英特尔手册第 6.12.1 章对此进行了详细介绍:
\n\n当处理器执行对异常或中断处理程序的调用时:
\n\n
\n- \n
如果处理程序过程要在数字较低的特权级别上执行,则会发生堆栈切换。\n发生堆栈切换时:
\n
\n-。处理程序要使用的堆栈的段选择器和堆栈指针是从当前正在执行的任务的 TSS 中获取的。在这个新堆栈上,处理器压入被中断过程的堆栈段选择器和堆栈指针。
\n[已编辑]- \n
如果处理程序过程将以与被中断过程相同的权限级别执行:\na。处理器将 EFLAGS、CS 和 EIP 寄存器的当前状态保存在当前堆栈上(参见图\n6-4)。
\n
\n[已编辑]
值得注意的是,在 64 位模式下,不再支持任务切换机制。
\n我们不能call或jmp或使用任务门。
\n然而,令人困惑的是,TSS 仍然被使用并且是强制性的。这种结构现在的使用方式与主流操作系统在实践中的使用方式一样:作为全局(读:每个任务都相同,至少在理论上)缓冲区来存储堆栈切换和其他信息。
\n还值得注意的是,在64位模式下,采用新的IST机制进行任务切换(参见第三版Intel手册第6.14.5节)。
\n\n如果我没有\xe2\x80\x99t 有这个 TSS ,它如何工作?是因为当中断发生时CPU仍然会自动推送EIP、CS、EFLAGS、EPS、SS并在iret上恢复它们吗?
\n
当没有特权级别更改时,CPU 将不会使用 TSS。要了解推送的内容以及推送的顺序,请参阅下图,取自英特尔手册第 3 卷:
\n\n\n\n如果我加载单个 TSS,该中断如何知道它应该使用该 TSS?使用ltr指令将在GDT内获取相应的tss段?
\n
当中断发生并且 CPU 意识到将要发生特权更改时,它将读取寄存器tr以达到当前的 TSS。
\n由于加载tr是一项特权操作,因此操作系统可以控制将使用什么 TSS。
\n事实上,如果操作系统想要对两个不同的程序Pa和Pb使用两个不同的TSS A和B ,则每次即将执行其中一个程序时,它都会重新加载。tr
所以是的,ltr指令就是操作系统如何控制当前活动的 TSS。
\n\n并不是真正相关,但是当使用硬件上下文切换并跳转到一个 TSS 时,它会在返回时自动跳转到上一个(没有下一个字段,所以 I\xe2\x80\x99m 有点丢失)tss 段吗?
\n
任务切换(如果支持)可以通过以下方式调用:jmp、call、int、中断或异常。
\n所有这些方法都会jmp将当前任务(正在切换的任务)链接到新任务(正在切换的任务)。
\n这是通过TSS 中的Previous Task Link字段实现的,新的 TSS 会将此字段设置为旧的 TSS 选择器。
\n据说新任务是嵌套的。
\nCPU 还将使用NT(嵌套任务)标志来跟踪当前任务是否嵌套。
如果任务是嵌套的(即使用call、int、 和中断或异常调用),则使用该iret指令,CPU 将读取上一个任务链接以查找要恢复的挂起任务。
请注意iret,即使任务切换是通过call(通常与 配对ret/retf)完成的,也可以使用 only 。
这是手册中的图片:
\n\n