ReactOS实现的兼容NT内核分析–KfLowerIrql函数_react指定内核

本文代码来自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级别的角度来 说是异步抢占的,在高级别他必须显式地执行代码来实现异步抢占,细粒度观察其实还是同步执行的。

原文链接: https://blog.csdn.net/dog250/article/details/5303595

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    ReactOS实现的兼容NT内核分析--KfLowerIrql函数_react指定内核

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/410083

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年4月26日 上午11:48
下一篇 2023年4月26日 上午11:48

相关推荐