在我看来,在为自己写一个完整的IDT时,还有很多工作要做。编写所有处理程序,等等。即使像宏观和"时代"指令来帮助你。如果是IDT 由256个qwords(或多或少)组成,用于保存有关用于调用的ir处理程序,标志,段选择器等的信息。让你自己进入pmode,选择一个内存位置并以编程方式创建你需要的所有内容会不容易?如果从地址0x7bfff开始,并构建所有256个条目,最多为0x7ffff,请确保为它们提供公共处理程序的地址,以便从,flags,selector,ect调用更具体的处理程序。然后你知道你的基础和限制。然后只需填写idt指针,加载它,并捕获它的工作原理。
答案 0 :(得分:1)
实用性始终是主观感知。因此,您的问题无法完全回答。尽管如此,我们可以查看一些支持和反对在运行时构建中断描述符表(IDT)的参数:
基本上,您的问题归结为是否在运行或编译时生成常量数据(IDT)。假设将生成相同数量的数据,无论何时,我们都有一些常见的参数:
在内核的上下文中,我可以想到以下情况需要在两个选项之间进行思考:
对于所有其他情况,在这样的"可衡量的"方面,并没有太大的区别。指标。考虑一下,有一些关于调试和运行时生成数据的权衡;使用静态IDT时,您甚至可以在运行内核之前对其进行验证。
这是实用性的另一个方面:
[..]编写所有处理程序,等等。即使像宏观和"时代"指令来帮助你。 [..]
这当然非常取决于您实际编写静态IDT的方式。基本上,没有人会阻止你编写一个(用户)程序来发出一个正确的IDT链接到你的内核,利用你将放入内核的相同代码(甚至更简单的代码)。因此,必须编写所有处理程序"是你的工具的缺陷,因此与在运行时是否生成它们没有直接关系。
在hobbyist kernel I wrote long ago我创建的处理程序(代码)"手工" (我现在会这样做^^)和运行时的实际IDT(数据):
// src/idt/idt.c
void IDT_SetGate (UINT8 num, UINT base, UINT16 sel, UINT8 flags)
{
UINT *tmp;
tmp = IDT;
tmp += num * 2;
*tmp = (base & 0xFFFF);
*tmp |= (sel & 0xFFFF) << 16;
tmp++;
*tmp = (flags & 0xFF) << 8;
*tmp |= (base & 0xFFFF0000);
}
// src/int/isr.c
void ISR_Setup (void)
{
IDT_SetGate(0, (unsigned)_isr0, 0x08, 0x8E);
IDT_SetGate(1, (unsigned)_isr1, 0x08, 0x8E);
// ... a lot more, an array would've been the better choice :D
}
然后我有了最小的处理程序_isr0
,_isr1
,...在保存中断号并处理错误代码后调用了一个公共处理程序。这是反对的主要论据:
[..]确保为他们提供一个公共处理程序的地址,以便从[..]中调用更具体的处理程序
至少在x86上,您需要为不同的中断使用不同的处理程序,否则您无法分辨触发的中断。要在运行时真正生成处理程序,您需要某种专用的汇编程序,这有助于您在运行时生成代码。我不会称那个&#34;实用&#34;了。