ReactOS实现的兼容NT内核分析--KfLowerIrql函数
来源:互联网 发布:通话变声器软件 编辑:程序博客网 时间:2024/05/21 05:37
本文代码来自ReactOS-0.3.6。
当硬件中断完成后将要返回的时候,将要调用KfLowerIrql来使当前cpu的irql降低到中断发生前的irql,但是真的就是直接降低到原来优先级就完事了吗?我们看看代码(桩代码,待会分析真正的):
VOID HalpLowerIrql(KIRQL NewIrql)
{
if (NewIrql >= PROFILE_LEVEL)//如果原来的优先级过高,啥也不说,直接恢复irql,然后返回
{
KeGetPcr()->Irql = NewIrql;
return;
}
HalpExecuteIrqs(NewIrql);//这个函数没什么用,可能是原来的实现吧,这个函数处理未决挂起的硬件中断
if (NewIrql >= DISPATCH_LEVEL)//如果原来irql在dispatch之上,那么返回,由此可知上面函数仅仅是个桩
{
KeGetPcr()->Irql = NewIrql;
return;
}
KeGetPcr()->Irql = DISPATCH_LEVEL;//从dispatch开始,因为到此处,原来irql肯定小于dispatch
if (((PKIPCR)KeGetPcr())->HalReserved[HAL_DPC_REQUEST])
{
((PKIPCR)KeGetPcr())->HalReserved[HAL_DPC_REQUEST] = FALSE;
KiDispatchInterrupt();
}
KeGetPcr()->Irql = APC_LEVEL;//往下依次处理irql递减的回调
if (NewIrql == APC_LEVEL)
{
return;
}
if (KeGetCurrentThread() != NULL &&
KeGetCurrentThread()->ApcState.KernelApcPending)
{
KiDeliverApc(KernelMode, NULL, NULL);
}
KeGetPcr()->Irql = PASSIVE_LEVEL;
}
从上面函数可知,并不是直接恢复原来的irql,而是依次按照优先级处理未决的虚拟中断。一不做二不休,姑且看一看那个没有什么用的函数:
VOID HalpExecuteIrqs(KIRQL NewIrql)
{
ULONG IrqLimit, i;
IrqLimit = min(PROFILE_LEVEL - NewIrql, NR_IRQS);
/*
* For each irq if there have been any deferred interrupts then now
* dispatch them.
*/
for (i = 0; i < IrqLimit; i++)
{
if (HalpPendingInterruptCount[i] > 0)
{
KeGetPcr()->Irql = (KIRQL)IRQ_TO_DIRQL(i);
while (HalpPendingInterruptCount[i] > 0)
{
/*
* For each deferred interrupt execute all the handlers at DIRQL.
*/
HalpPendingInterruptCount[i]--;
//HalpHardwareInt[i]();//不知为什么被注释了,这样不挺好吗?
}
//KeGetPcr()->Irql--;
//HalpEndSystemInterrupt(KeGetPcr()->Irql);
}
}
}
HalpLowerIrql 很重要,整个系统的每个部分都有它的身影,实际上,就是它实现了虚拟中断控制器的重要部分,可畏的是,nt内核竟然实现的如此巧妙,以至于程序员不需要面 对真正的硬件处理而只需要面对irql就可以了,下面我们看看ms在x86下的kflowerirql源代码:
VOID FASTCALL KfLowerIrql (KIRQL NewIrql)
{
KIRQL oldIrql = KeGetCurrentIrql();
if (NewIrql > oldIrql)
{
DPRINT1 ("NewIrql %x CurrentIrql %x/n", NewIrql, oldIrql);
KEBUGCHECK (0);
}
HalpLowerIrql (NewIrql, FALSE);//Kf函数仅仅是Hal的包装函数,实现一些检查,不通过就蓝!
}
VOID HalpLowerIrql(KIRQL NewIrql, BOOLEAN FromHalEndSystemInterrupt)
{
ULONG Flags;
UCHAR DpcRequested;
if (NewIrql >= DISPATCH_LEVEL)
{
KeSetCurrentIrql (NewIrql);
APICWrite(APIC_TPR, IRQL2TPR (NewIrql) & APIC_TPR_PRI);
return;
}
Ke386SaveFlags(Flags);
if (KeGetCurrentIrql() > APC_LEVEL)
{
KeSetCurrentIrql (DISPATCH_LEVEL);
APICWrite(APIC_TPR, IRQL2TPR (DISPATCH_LEVEL) & APIC_TPR_PRI);//虚拟与真实的通信
DpcRequested = __readfsbyte(FIELD_OFFSET(KIPCR, HalReserved[HAL_DPC_REQUEST])); //读取一个位,以检测是否有软件中断发生,这个位是在Request软件中断的函数里面设置的。
if (FromHalEndSystemInterrupt || DpcRequested)
{
__writefsbyte(FIELD_OFFSET(KIPCR, HalReserved[HAL_DPC_REQUEST]), 0);
_enable();
KiDispatchInterrupt();//分发dpc过程,实际上就是一个一个执行。最后再看看有没有需要切换的线程
if (!(Flags & EFLAGS_INTERRUPT_MASK))
{
_disable();
}
}
KeSetCurrentIrql (APC_LEVEL);
}
if (NewIrql == APC_LEVEL)
{
return;
}
if (KeGetCurrentThread () != NULL &&
KeGetCurrentThread ()->ApcState.KernelApcPending)//注意,apc在费任意线程上下文进行,所以apc级别往下就不能什么都揉在一起了,就要按照进程分别对待了。
{
_enable();
KiDeliverApc(KernelMode, NULL, NULL);
if (!(Flags & EFLAGS_INTERRUPT_MASK))
{
_disable();
}
}
KeSetCurrentIrql (PASSIVE_LEVEL);
}
对 比一下两个kflowerirql,都是一级一级 往下跳变,根本不是直接就降到原来的优先级的。软件毕竟不是硬件,可以真正神不知鬼不觉地实现抢占,它只是在用户的角度,在passtive级别的角度来 说是异步抢占的,在高级别他必须显式地执行代码来实现异步抢占,细粒度观察其实还是同步执行的。
- ReactOS实现的兼容NT内核分析--KfLowerIrql函数
- ReactOS实现的兼容NT内核分析--KfLowerIrql函数
- 开源并兼容Windows NT的操作系统ReactOS简介
- 漫谈兼容内核之一:ReactOS怎样实现系统调用
- 漫谈兼容内核之一:ReactOS怎样实现系统调用
- 漫谈兼容内核之一:ReactOS 怎样实现系统调用
- ReactOS分析MDL实现
- NT 内核的进程调度分析笔记
- Windows NT内核分析
- NT内核代码分析
- Windows NT内核分析
- Windows NT内核分析
- NT内核代码分析
- 内核解惑:zw函数和nt函数的区别
- 漫谈兼容内核:ReactOS怎样实现系统调用http://www.linuxsir.org/bbs/showthread.php?t=232200
- 漫谈兼容内核:ReactOS怎样实现系统调用http://www.linuxsir.org/bbs/showthread.php?t=232200
- [转载]NT 内核的进程调度分析笔记
- 内核态调用Nt*函数
- ALAsset,ALAssetsLibrary,ALAssetsgroup常见属性及用法
- ajax上传文件和csv文件读写
- 一个10年的程序员的感叹!
- Jenkins权限设计错误解决办法
- 魅族系列手机无法连接eclipse解决办法
- ReactOS实现的兼容NT内核分析--KfLowerIrql函数
- String——第一个只出现一次的字符
- POJ 2159 Going Home 网络流 最小费用最大流
- 视图
- 模式识别入门学习
- web.xml详解
- C strlen
- 第十二周上机实践项目-项目1-(2)-阅读程序
- 在Google被封怎么上网,怎么工作,其实我们不需要用vpn也能上网