第四章 探索 windows 2000 的内存管理机制
翻译: kendiv( fcczj@263.net )
更新: sunday, february 17, 2005
声明:转载请注明出处,并保证文章的完整性,本人保留译文的所有权利。
ioctl 函数 spy_io_interrupt
spy_io_interrup 类似于 spy_io_segemt ,不过该函数仅影响存储在系统中断描述符表( idt )的中断描述符,不会涉及 ldt 或 gdt 描述符。 idt 最多可容纳 256 个描述符,这些描述符可用来描述任务门、中断门或陷阱门(参见 intel 1999c, pp. 5-11ff )。顺便说一下,中断和陷阱在本质上十分相似,二者只存在微小的差异:在进入一个中断处理例程后,总是会屏蔽其他中断;而进入陷阱处理例程却不会修改中断标志。 spy_io_interrupt 的调用者提供一个 0 到 255 之间的中断号,该中断号将位于输入缓冲区中,而一个 spy_interrupt 结构将作为输出数据被存放到输出缓冲区中,如果成功返回,该结构中将包含对应的中断处理例程的属性。由 dispatcher 调用的帮助函数 spyoutputinterrupt() 只是一个简单的外包函数,它实际上调用 spyinterrupt() 函数并且将需要返回的数据复制到输出缓冲区中。 列表 4-18 给出了这两个函数,以及它们操作的 spy_interrupt 结构。稍后一些, spyinterrupt() 函数将填充如下项目:
l selector 用来指定一个任务状态段( task-state segment, tss )或代码段( code segment )的选择器。代码段选择器用来确定中断或陷阱处理例程所在的段。
l gate 用来表示一个 64 位的任务门、中断门或陷阱门描述符,由 selector 确定其地址。
l segment 包含段的属性,该段的地址由前面的 gate 给出。
l poffset 指定中断或陷阱处理例程的入口地址相对基地址的偏移量。这里的基地址是指中断或陷阱处理例程所在代码段的起始地址。因为任务门不包含偏移量,所以,如果输入的选择器指向一个 tss ,则忽略该成员。
l fok 一个标志变量,用来指示 spy_interrupt 结构中的数据是否有效。
通常情况下, tss 被用来保证一个错误情况可以被一个有效的任务处理。这是一个特殊的系统段类型( system segment type ),它可以保存 104 个字节的进程状态信息,该信息在任务切换时,用来进行任务的恢复,如 表 4-3 所示。当与任务相关的中断发生时, cpu 总是强制切换该任务,并将所有的 cpu 寄存器保存到 tss 中。 windows 2000 在中断位置 0x02 (非屏蔽中断 [nmi] , 0x08[double fault] 和 0x12[ 堆栈段故障 ] )处保存任务门。剩余的位置指向中断处理例程。不使用的中断由一个哑元例程 ---kiunexpectedinterruptnnn() 处理,这里的 nnn 为一个十进制数。这些哑元例程最后都汇集到内部函数 kiendunexpectedrange() ,在这里,这些例程将依次进入 kiunexpectedinterrupttail() 。
typedef struct _spy_interrupt
{
x86_selector selector;
x86_gate gate;
spy_segment segment;
pvoid poffset;
bool fok;
}
spy_interrupt, *pspy_interrupt, **ppspy_interrupt;
#define spy_interrupt_ sizeof (spy_interrupt)
// -----------------------------------------------------------------
ntstatus spyoutputinterrupt (dword dinterrupt,
pvoid poutput,
dword doutput,
pdword pdinfo)
{
spy_interrupt si;
spyinterrupt (dinterrupt, &si);
return spyoutputbinary (&si, spy_interrupt_,
poutput, doutput, pdinfo);
}
// -----------------------------------------------------------------
bool spyinterrupt (dword dinterrupt,
pspy_interrupt pinterrupt)
{
bool fok = false;
if (pinterrupt != null)
{
if (dinterrupt <= x86_selector_limit)
{
fok = true;
if (!spyselector (x86_segment_other,
dinterrupt << x86_selector_shift,
&pinterrupt->selector))
{
fok = false;
}
if (!spyidtgate (&pinterrupt->selector,
&pinterrupt->gate))
{
fok = false;
}
if (!spysegment (x86_segment_other,
pinterrupt->gate.selector,
&pinterrupt->segment))
{
fok = false;
}
pinterrupt->poffset = spygateoffset (&pinterrupt->gate);
}
else
{
rtlzeromemory (pinterrupt, spy_interrupt_);
}
pinterrupt->fok = fok;
}
return fok;
}
// -----------------------------------------------------------------
pvoid spygateoffset (px86_gate pgate)
{
return (pvoid) (pgate->offset1 (pgate->offset2 << 16));
}
列表 4-18. 查询中断属性
表 4-3. 任务状态段( tss )中的 cpu 状态域
偏移量 | 位数 | id | 描 述 |